From e9ca69427bc09303463370114575fe8255c7ce09 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 12 Aug 2026 02:20:56 +0000 Subject: [PATCH 1/5] Bump nanoid from 3.3.12 to 3.3.18 Bumps [nanoid](https://github.com/ai/nanoid) from 3.3.12 to 3.3.18. - [Release notes](https://github.com/ai/nanoid/releases) - [Changelog](https://github.com/ai/nanoid/blob/3.3.18/CHANGELOG.md) - [Commits](https://github.com/ai/nanoid/compare/3.3.12...3.3.18) --- updated-dependencies: - dependency-name: nanoid dependency-version: 3.3.18 dependency-type: indirect ... Signed-off-by: dependabot[bot] --- package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0f8c654..a0aa307 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4129,9 +4129,9 @@ "license": "MIT" }, "node_modules/nanoid": { - "version": "3.3.12", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", - "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", + "version": "3.3.18", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.18.tgz", + "integrity": "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==", "funding": [ { "type": "github", From f953144c1a394ebbe5191065bc5140219b0729f0 Mon Sep 17 00:00:00 2001 From: Paulino Calderon Date: Mon, 24 Aug 2026 07:39:04 +0000 Subject: [PATCH 2/5] Remove em and en dashes from all content Rewrite dashes across controls, tools, resources, data files, pages and docs using natural language: commas, colons or separate sentences for prose, and "X to Y" for ranges. Compound hyphens, code, URLs and IDs are unchanged. Site builds and content validation passes. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01TusCA8RGdnAjPAjCyA6Zii --- CONTRIBUTING.md | 22 +++--- CONTROLS-AUTHORING.md | 38 ++++----- README.md | 10 +-- WAYFINDER-AUTHORING.md | 32 ++++---- src/components/DefersToBsam.astro | 2 +- src/components/References.astro | 2 +- src/content/controls/_template.md | 2 +- src/content/controls/rfsam-adsb-ll-01.md | 28 +++---- src/content/controls/rfsam-adsb-phy-01.md | 42 +++++----- src/content/controls/rfsam-ble-at-01.md | 14 ++-- src/content/controls/rfsam-ble-cr-01.md | 28 +++---- src/content/controls/rfsam-ble-ig-01.md | 36 ++++----- src/content/controls/rfsam-ble-ll-01.md | 28 +++---- src/content/controls/rfsam-ble-ll-02.md | 46 +++++------ src/content/controls/rfsam-ble-phy-01.md | 54 ++++++------- src/content/controls/rfsam-ble-sp-01.md | 40 +++++----- src/content/controls/rfsam-btc-ap-01.md | 48 ++++++------ src/content/controls/rfsam-btc-at-01.md | 56 ++++++------- src/content/controls/rfsam-btc-cr-01.md | 36 ++++----- src/content/controls/rfsam-btc-ig-01.md | 50 ++++++------ src/content/controls/rfsam-btc-ll-01.md | 32 ++++---- src/content/controls/rfsam-btc-sp-01.md | 62 +++++++-------- src/content/controls/rfsam-gnss-at-01.md | 38 ++++----- src/content/controls/rfsam-gnss-sp-01.md | 40 +++++----- src/content/controls/rfsam-gsm-cr-01.md | 42 +++++----- src/content/controls/rfsam-gsm-sp-01.md | 44 +++++------ src/content/controls/rfsam-lora-cr-01.md | 52 ++++++------- src/content/controls/rfsam-lora-ll-01.md | 44 +++++------ src/content/controls/rfsam-lora-phy-01.md | 40 +++++----- src/content/controls/rfsam-lora-sp-01.md | 40 +++++----- src/content/controls/rfsam-lte-ig-01.md | 30 +++---- src/content/controls/rfsam-lte-ll-01.md | 40 +++++----- src/content/controls/rfsam-lte-phy-01.md | 28 +++---- src/content/controls/rfsam-lte-sp-01.md | 54 ++++++------- src/content/controls/rfsam-nr5g-ll-01.md | 54 ++++++------- src/content/controls/rfsam-nr5g-sp-01.md | 56 ++++++------- src/content/controls/rfsam-rfid-at-01.md | 40 +++++----- src/content/controls/rfsam-rfid-cr-01.md | 78 +++++++++---------- src/content/controls/rfsam-rfid-sp-01.md | 42 +++++----- src/content/controls/rfsam-subg-at-01.md | 52 ++++++------- src/content/controls/rfsam-subg-cr-01.md | 32 ++++---- src/content/controls/rfsam-subg-ll-01.md | 38 ++++----- src/content/controls/rfsam-subg-phy-01.md | 46 +++++------ src/content/controls/rfsam-subg-sp-01.md | 42 +++++----- src/content/controls/rfsam-thread-cr-01.md | 38 ++++----- src/content/controls/rfsam-thread-ll-01.md | 36 ++++----- src/content/controls/rfsam-uwb-at-01.md | 48 ++++++------ src/content/controls/rfsam-uwb-phy-01.md | 38 ++++----- src/content/controls/rfsam-wifi-cr-01.md | 40 +++++----- src/content/controls/rfsam-wifi-ll-01.md | 44 +++++------ src/content/controls/rfsam-wifi-sp-01.md | 60 +++++++------- src/content/controls/rfsam-zigbee-cr-01.md | 46 +++++------ src/content/controls/rfsam-zigbee-ll-01.md | 34 ++++---- src/content/controls/rfsam-zigbee-sp-01.md | 44 +++++------ src/content/controls/rfsam-zwave-cr-01.md | 48 ++++++------ src/content/controls/rfsam-zwave-sp-01.md | 59 +++++++------- src/content/resources/rfsam-res-01.md | 2 +- src/content/resources/rfsam-res-07.md | 2 +- src/content/resources/rfsam-res-15.md | 2 +- src/content/resources/rfsam-res-16.md | 2 +- src/content/resources/rfsam-res-17.md | 2 +- src/content/resources/rfsam-res-20.md | 2 +- src/content/resources/rfsam-res-21.md | 2 +- src/content/resources/rfsam-res-22.md | 2 +- src/content/resources/rfsam-res-23.md | 2 +- src/content/resources/rfsam-res-24.md | 2 +- src/content/resources/rfsam-res-25.md | 2 +- src/content/resources/rfsam-res-26.md | 2 +- src/content/resources/rfsam-res-27.md | 2 +- src/content/resources/rfsam-res-28.md | 2 +- src/content/resources/rfsam-res-29.md | 2 +- src/content/tools/5greplay.md | 4 +- src/content/tools/5gsniffer.md | 4 +- src/content/tools/acr122u.md | 4 +- src/content/tools/adsb-out.md | 6 +- src/content/tools/alfa-awus036ach.md | 4 +- src/content/tools/apimote.md | 4 +- src/content/tools/applejuice.md | 4 +- src/content/tools/bbc-microbit.md | 4 +- src/content/tools/bladerf-2-micro.md | 6 +- src/content/tools/braktooth.md | 6 +- src/content/tools/cc2531.md | 4 +- src/content/tools/chip-repl.md | 4 +- src/content/tools/chip-tool.md | 6 +- src/content/tools/chirpcat.md | 4 +- src/content/tools/chirpstack.md | 4 +- src/content/tools/connectedhomeip.md | 4 +- src/content/tools/cyd.md | 6 +- src/content/tools/dwm3000-dwt-driver.md | 4 +- src/content/tools/dwm3000evb.md | 5 +- src/content/tools/esp32-airtag-scanner.md | 4 +- src/content/tools/esp32-bluejammer.md | 4 +- src/content/tools/esp32-bt-classic-sniffer.md | 6 +- src/content/tools/esp32-bt-exp.md | 4 +- src/content/tools/esp32-classic-bt-scan.md | 4 +- src/content/tools/esp32-deauther-ganesh.md | 4 +- src/content/tools/esp32-devkit.md | 6 +- src/content/tools/esp32-marauder.md | 6 +- src/content/tools/esp32-projectzero.md | 4 +- src/content/tools/esp32-s3-devkit.md | 6 +- src/content/tools/esp32-sour-apple.md | 6 +- .../tools/esp32-wifi-penetration-tool.md | 4 +- src/content/tools/evilapplejuice-esp32.md | 5 +- src/content/tools/ez-wave.md | 4 +- src/content/tools/falcon.md | 4 +- src/content/tools/flipper-wifi-devboard.md | 6 +- src/content/tools/flipper-zero.md | 6 +- src/content/tools/flipperzero-firmware.md | 4 +- src/content/tools/forthink-uwb-dongle.md | 4 +- src/content/tools/forthink-uwb-sniffer.md | 6 +- src/content/tools/free5gc.md | 4 +- src/content/tools/gnss-sdr.md | 6 +- src/content/tools/gps-sdr-sim.md | 6 +- src/content/tools/gpsd.md | 4 +- src/content/tools/gqrx.md | 4 +- src/content/tools/gr-air-modes.md | 4 +- src/content/tools/hackrf-one.md | 6 +- src/content/tools/hashcat.md | 4 +- src/content/tools/hcxtools.md | 4 +- src/content/tools/hostapd-mana.md | 4 +- src/content/tools/ice9-bluetooth-sniffer.md | 4 +- src/content/tools/imsi-catcher-srsran.md | 4 +- src/content/tools/imsi-catcher.md | 4 +- src/content/tools/killerbee.md | 4 +- src/content/tools/kismet.md | 6 +- src/content/tools/kraken-a51.md | 4 +- src/content/tools/laf.md | 4 +- src/content/tools/libnfc.md | 5 +- src/content/tools/lora-wideband-decoder.md | 4 +- src/content/tools/m5-cardputer.md | 4 +- .../tools/makerfabs-esp32-uwb-dw3000.md | 4 +- src/content/tools/marauder-ui-android-app.md | 4 +- src/content/tools/matter-dcl.md | 6 +- src/content/tools/mdek1001.md | 6 +- src/content/tools/mdk4.md | 4 +- src/content/tools/mfcuk.md | 4 +- src/content/tools/mfdread.md | 6 +- src/content/tools/minino.md | 6 +- src/content/tools/murata-type2bp.md | 7 +- src/content/tools/openairinterface5g.md | 4 +- src/content/tools/openhaystack.md | 4 +- src/content/tools/orbic-rc400l.md | 6 +- src/content/tools/osmo-bts.md | 4 +- src/content/tools/pm3-client.md | 4 +- src/content/tools/pymodes.md | 6 +- src/content/tools/python-matter-server.md | 4 +- src/content/tools/qcsuper.md | 4 +- src/content/tools/quectel-rm500q.md | 4 +- src/content/tools/rak-wisgate-connect.md | 4 +- src/content/tools/rayhunter.md | 4 +- src/content/tools/rtl-433.md | 6 +- src/content/tools/rtl-sdr-v4.md | 6 +- src/content/tools/rtl-zwave.md | 4 +- src/content/tools/scapy-radio.md | 4 +- src/content/tools/seemoo-uwb-sniffer.md | 4 +- src/content/tools/signalsdr-pro.md | 6 +- src/content/tools/silabs-uzb7.md | 5 +- src/content/tools/sim7600.md | 6 +- src/content/tools/sni5gect.md | 4 +- src/content/tools/sniffle.md | 4 +- src/content/tools/srsran-4g.md | 4 +- src/content/tools/srsran-project.md | 4 +- src/content/tools/stm32wlxx.md | 4 +- src/content/tools/ublox-neo-gps.md | 4 +- src/content/tools/universal-radio-hacker.md | 4 +- src/content/tools/usrp-b210.md | 2 +- src/content/tools/whad.md | 6 +- src/content/tools/whsniff.md | 4 +- src/content/tools/wireshark.md | 4 +- src/content/tools/yard-stick-one.md | 4 +- src/content/tools/zbdsniff.md | 4 +- src/content/tools/zwave-pc-controller.md | 4 +- src/content/tools/zwave-zniffer.md | 4 +- src/data/protocol-tools/adsb.json | 6 +- src/data/protocol-tools/esp32.json | 44 +++++------ src/data/protocol-tools/gnss.json | 8 +- src/data/protocol-tools/gsm.json | 6 +- src/data/protocol-tools/lora.json | 10 +-- src/data/protocol-tools/lte.json | 18 ++--- src/data/protocol-tools/nr5g.json | 10 +-- src/data/protocol-tools/rfid.json | 10 +-- src/data/protocol-tools/subg.json | 8 +- src/data/protocol-tools/thread.json | 10 +-- src/data/protocol-tools/uwb.json | 18 ++--- src/data/protocol-tools/zigbee.json | 10 +-- src/data/protocol-tools/zwave.json | 12 +-- src/layouts/BaseLayout.astro | 4 +- src/pages/controls/[...slug].astro | 6 +- src/pages/index.astro | 14 ++-- src/pages/methodology.astro | 16 ++-- src/pages/roadmap.astro | 18 ++--- src/pages/tools.astro | 4 +- src/pages/tools/[slug].astro | 2 +- src/pages/wayfinder/[protocol].astro | 12 +-- 194 files changed, 1477 insertions(+), 1483 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1870d67..77b1f04 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,17 +1,17 @@ # Contributing to RFSAM -RFSAM grows by pull request. A good contribution is a control that is **accurate, cited, and reproducible** — wrong depth is worse than missing depth, so every nontrivial claim must carry a source you can check. +RFSAM grows by pull request. A good contribution is a control that is **accurate, cited, and reproducible**: wrong depth is worse than missing depth, so every nontrivial claim must carry a source you can check. ## Add a control 1. Copy `src/content/controls/_template.md` to `src/content/controls/.md`, where `` is the lower-cased control ID (e.g. `rfsam-zigbee-cr-01.md`). 2. Fill the frontmatter and the body sections. -3. Run `npm run validate` and `npm run build` — both must pass. +3. Run `npm run validate` and `npm run build`: both must pass. 4. Open a pull request. ## The control ID -`RFSAM---` — e.g. `RFSAM-BLE-AT-01`. +`RFSAM---`, e.g. `RFSAM-BLE-AT-01`. - `` is one of the protocol ids (`BLE`, `WIFI`, `LORA`, `LTE`, `RFID`, `SUBG`, `ZIGBEE`, `ZWAVE`, `THREAD`, `GNSS`, `ADSB`, `NR5G`, `GSM`, `UWB`). - `` is one of `IG SP PHY LL CR AT AP`. @@ -31,24 +31,24 @@ Frontmatter (validated by `src/content.config.ts` and `scripts/validate.mjs`): | `objective` | one testable statement of what the control verifies (required once `draft`/`verified`) | | `intro` | short callout shown above the body | | `prerequisites` | `hardware[]`, `software[]`, `signal{freq,bandwidth,modulation}`, `skill` | -| `attacks[]` | `{name, cve?, refs[], impact, preconditions, summary}` — each `refs` key MUST exist in `references` | +| `attacks[]` | `{name, cve?, refs[], impact, preconditions, summary}`; each `refs` key MUST exist in `references` | | `references[]` | `{key, title, authors?, venue?, year?, url, type}`; `type ∈ paper cve talk spec standard tool blog` | | `tools[]` | slugs that exist in `src/content/tools/` | | `bsam[]` | ids that exist in the BSAM registry (`src/data/bsam.js`) | | `resources[]` | `RFSAM-RES-NN` ids that exist in `src/content/resources/` | | `reviewStatus` | `stub` → `draft` → `verified` | -| `confidence` | `low medium high` — honest self-assessment of the draft | +| `confidence` | `low medium high`: honest self-assessment of the draft | | `lastResearched` | date the sources were pulled | Body sections, in order: `## Mechanism`, `## Procedure`, `## Field case`, `## Remediation`. Put real commands in fenced code blocks with the expected output. Preserve command strings verbatim. ## Criticality rubric -- **info** — observational; no direct security impact (e.g. capture feasibility). -- **low** — minor exposure or hardening gap. -- **medium** — meaningful weakness requiring specific conditions to exploit. -- **high** — readily exploitable weakness with significant impact. -- **critical** — full compromise (takeover, key recovery, impersonation) with practical preconditions. +- **info**: observational; no direct security impact (e.g. capture feasibility). +- **low**: minor exposure or hardening gap. +- **medium**: meaningful weakness requiring specific conditions to exploit. +- **high**: readily exploitable weakness with significant impact. +- **critical**: full compromise (takeover, key recovery, impersonation) with practical preconditions. ## Research → verify workflow @@ -56,7 +56,7 @@ Body sections, in order: `## Mechanism`, `## Procedure`, `## Field case`, `## Re 2. **Draft** to the schema. Every nontrivial claim in `## Mechanism` and every attack maps to a reference. Set `reviewStatus: draft`. 3. **Be honest about uncertainty.** Set `confidence` accordingly, and mark any claim you could not fully verify: ``` - > [!FLAG] the claim — what still needs to be checked + > [!FLAG] the claim: what still needs to be checked ``` 4. **Verify.** A reviewer resolves the flags and confirms the citations, then sets `reviewStatus: verified`. A `verified` control must carry at least one reference and contain no unresolved `[!FLAG]`. diff --git a/CONTROLS-AUTHORING.md b/CONTROLS-AUTHORING.md index f318700..1b07243 100644 --- a/CONTROLS-AUTHORING.md +++ b/CONTROLS-AUTHORING.md @@ -1,13 +1,13 @@ # Controls authoring rules -How to research and write an RFSAM **control** — one numbered, cited, reproducible +How to research and write an RFSAM **control**: one numbered, cited, reproducible verification procedure for a single *protocol × layer*. This is the brief a contributor or a sub-agent follows. The machine-checkable schema lives in `src/content.config.ts`; the human PR flow, the field-by-field table and the criticality rubric live in **`CONTRIBUTING.md`**; copy **`src/content/controls/_template.md`** to start; **`rfsam-ble-at-01.md`** is -the reference depth. This file is the *operational* guide — what makes a control +the reference depth. This file is the *operational* guide: what makes a control accurate, reproducible, and consistent with the rest of RFSAM. --- @@ -21,8 +21,8 @@ procedure with real commands) and **cited** (every nontrivial claim carries a resolvable source). Wrong depth is worse than missing depth. A control is **not** the Wayfinder. The Wayfinder (`src/data/toolchains/.js`) -is the *kit map* — what hardware + software to use at each step. A control is the -*method and the finding* — how to run the check, a real worked example, the known +is the *kit map*: what hardware + software to use at each step. A control is the +*method and the finding*: how to run the check, a real worked example, the known attacks with references, and the remediation. They are **paired**: a control's `layer`, `tools[]` and `attacks[]` must be consistent with that protocol's Wayfinder toolchain at the same layer (read it first; the bands, tools and attack framing are @@ -32,7 +32,7 @@ already researched there). ## File & ID -- One control per file: `src/content/controls/.md` — e.g. `rfsam-zwave-cr-01.md`. +- One control per file: `src/content/controls/.md`, e.g. `rfsam-zwave-cr-01.md`. - `id` = `RFSAM---`. **Invariant: the PROTOCOL and LAYER segments MUST equal the `protocol` and `layer` frontmatter fields.** The validator fails otherwise. - Protocols: `BLE WIFI LORA LTE RFID SUBG ZIGBEE ZWAVE THREAD GNSS ADSB NR5G GSM UWB`. Layers: `IG SP PHY LL CR AT AP`. @@ -40,7 +40,7 @@ already researched there). Full schema + table: `CONTRIBUTING.md` / `src/content.config.ts`. The must-gets: - `title` short + imperative; `criticality` per the rubric; `objective` = the one testable thing it verifies (required once `draft`). -- `prerequisites { hardware[], software[], signal{freq,bandwidth,modulation}, skill }` — pull the signal facts from the protocol's Wayfinder `facts`. +- `prerequisites { hardware[], software[], signal{freq,bandwidth,modulation}, skill }`; pull the signal facts from the protocol's Wayfinder `facts`. - `attacks[]` = named real attacks `{name, cve?, refs[], impact, preconditions, summary}`. **Every `refs` key MUST exist in `references[]`.** - `references[]` = `{key, title, authors?, venue?, year?, url, type}`. **Every `url` must resolve and actually be the cited work.** - `tools[]` = slugs that exist in `src/content/tools/` (reuse the protocol's Wayfinder tools). @@ -48,26 +48,26 @@ Full schema + table: `CONTRIBUTING.md` / `src/content.config.ts`. The must-gets: - `resources[]` = `RFSAM-RES-NN` ids that exist in `src/content/resources/`. - `reviewStatus` + `confidence` (lifecycle below); `lastResearched` = the date you pulled the sources. -## Body — four sections, in order +## Body: four sections, in order `## Mechanism` → `## Procedure` → `## Field case` → `## Remediation`. -- **Mechanism** — how the RF/protocol works and why the control matters. Every nontrivial claim cites a `references[]` key. Name the real attack families. -- **Procedure** — a NUMBERED, reproducible method, with real commands in fenced code blocks and the expected output / how to read it. Preserve command strings verbatim. -- **Field case** — a concrete worked example with real data (the war story). Keep author field data and any intentional `[FILL: …]` placeholder verbatim — do NOT fabricate a finding. -- **Remediation** — specific, layered guidance (developer / integrator / operator). +- **Mechanism**: how the RF/protocol works and why the control matters. Every nontrivial claim cites a `references[]` key. Name the real attack families. +- **Procedure**: a NUMBERED, reproducible method, with real commands in fenced code blocks and the expected output / how to read it. Preserve command strings verbatim. +- **Field case**: a concrete worked example with real data (the war story). Keep author field data and any intentional `[FILL: …]` placeholder verbatim; do NOT fabricate a finding. +- **Remediation**: specific, layered guidance (developer / integrator / operator). --- ## The ten rules (accuracy first) -1. **Cite or flag everything.** Every nontrivial claim, attack and number maps to a resolvable `references[]` entry. Verify each source actually exists and says what you claim — `gh api repos//` for a tool, the NVD page for a CVE, the real paper/talk URL. Never assert what you can't cite. (`[[no-unverified-claims]]`) -2. **Flag uncertainty inline:** `> [!FLAG] the claim — what still needs checking`. A `draft` may carry flags; a `verified` control must have none. +1. **Cite or flag everything.** Every nontrivial claim, attack and number maps to a resolvable `references[]` entry. Verify each source actually exists and says what you claim: `gh api repos//` for a tool, the NVD page for a CVE, the real paper/talk URL. Never assert what you can't cite. (`[[no-unverified-claims]]`) +2. **Flag uncertainty inline:** `> [!FLAG] the claim: what still needs checking`. A `draft` may carry flags; a `verified` control must have none. 3. **A sub-agent produces `draft`, never `verified`.** Verification is a separate review pass that resolves the flags and confirms the citations. Set `confidence` honestly (`low`/`medium`/`high`). -4. **Align with the Wayfinder.** Read `src/data/toolchains/.js` for this layer first: reuse its `facts` (bands/modulation), its tools (as `tools[]`), and its attack framing. A control *deepens* what the Wayfinder summarises — they must not contradict. -5. **BSAM deference.** Where BSAM owns the layer (BLE link-and-above; the deferred IG controls), set `deferred: true`, cite the specific `bsam[]` ids, and describe ONLY the RF-capture prerequisite that reaches the point where the BSAM control applies — do not re-derive BSAM's content. (`src/data/bsamRelation.js`) +4. **Align with the Wayfinder.** Read `src/data/toolchains/.js` for this layer first: reuse its `facts` (bands/modulation), its tools (as `tools[]`), and its attack framing. A control *deepens* what the Wayfinder summarises; they must not contradict. +5. **BSAM deference.** Where BSAM owns the layer (BLE link-and-above; the deferred IG controls), set `deferred: true`, cite the specific `bsam[]` ids, and describe ONLY the RF-capture prerequisite that reaches the point where the BSAM control applies; do not re-derive BSAM's content. (`src/data/bsamRelation.js`) 6. **Tone: a north, not novelty.** RFSAM orients and organises; it builds on OSSTMM / BSAM / the SDR-pentest lineage. Never "first / nobody does this / invented". Frame tool & CVE corpora as "representative, check current advisories". 7. **Authorised-testing framing** on every active / transmit / decrypt step (rogue cells, replay, key recovery): your own equipment, test SIMs/devices, RF shielding, explicit permission. -8. **Verbatim load-bearing content.** Monospace command strings, war-story values (`cur_aa`, `w 0x000e 7e 07 05 03 ff 00 00 10 ef`) and `[FILL: …]` notes are kept exactly — never paraphrase, "complete", or invent them. +8. **Verbatim load-bearing content.** Monospace command strings, war-story values (`cur_aa`, `w 0x000e 7e 07 05 03 ff 00 00 10 ef`) and `[FILL: …]` notes are kept exactly; never paraphrase, "complete", or invent them. 9. **Criticality honestly** per the CONTRIBUTING rubric (info → critical). Observational capture-feasibility is `info`/`low`; full takeover / key recovery / impersonation is `high`/`critical`. 10. **It must validate and build.** Controls don't need `seed-tools`, but `npm run validate` (cross-refs) and `npm run build` (zod schema) MUST pass. The validator checks: id ↔ protocol ↔ layer; every `tools` / `bsam` / `resources` / attack-`refs` reference resolves; enums valid; no empty required fields. @@ -75,12 +75,12 @@ Full schema + table: `CONTRIBUTING.md` / `src/content.config.ts`. The must-gets: ## reviewStatus / confidence lifecycle -`stub` (placeholder, little real content) → `draft` (researched, cited, may carry `[!FLAG]`s — what a sub-agent produces) → `verified` (a reviewer resolved every flag and confirmed every citation; ≥ 1 reference, zero unresolved flags). Sub-agents stop at `draft`. +`stub` (placeholder, little real content) → `draft` (researched, cited, may carry `[!FLAG]`s, what a sub-agent produces) → `verified` (a reviewer resolved every flag and confirmed every citation; ≥ 1 reference, zero unresolved flags). Sub-agents stop at `draft`. ## What to write (coverage) `src/data/coverage-map.js` and the `/roadmap` page list every control: `existing` -(a file exists — but most are `stub`s needing depth) and `planned` (proposed scope, +(a file exists, but most are `stub`s needing depth) and `planned` (proposed scope, unwritten). A sub-agent task is usually **either** deepen one existing stub to `draft`, **or** write one planned control to `draft`. **One control per sub-agent.** @@ -89,7 +89,7 @@ unwritten). A sub-agent task is usually **either** deepen one existing stub to Give each sub-agent ONE control id. Tell it to: 1. Read this file, `_template.md`, `CONTRIBUTING.md`, the protocol's Wayfinder (`src/data/toolchains/.js`), and the existing stub if any. -2. Research and **verify every source** (gh/web) — papers, CVEs (NVD), specs, tool repos, talks. +2. Research and **verify every source** (gh/web): papers, CVEs (NVD), specs, tool repos, talks. 3. Write `src/content/controls/.md` as `reviewStatus: draft` with an honest `confidence`, citing every claim and `[!FLAG]`-ing anything it could not fully verify. 4. NOT run the shared `seed-tools` (controls don't need it); just self-check the diff --git a/README.md b/README.md index d118cf1..4b76011 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,14 @@ -# RFSAM — Radio Frequency Security Assessment Methodology +# RFSAM: Radio Frequency Security Assessment Methodology An open, structured methodology for RF research and auditing, by [Electronic Cats](https://electroniccats.com) and [PWNLabs](https://pwnlab.mx). -RFSAM is meant to be **a north** for RF work: faced with an unknown signal or device, where do you start — and how do you know what you've missed? It walks you from the spectrum up through the signal, link, crypto, attack and application layers, per protocol, with a verification procedure and a real worked example at each step. +RFSAM is meant to be **a north** for RF work: faced with an unknown signal or device, where do you start, and how do you know what you've missed? It walks you from the spectrum up through the signal, link, crypto, attack and application layers, per protocol, with a verification procedure and a real worked example at each step. It does **not** claim to invent RF security. OSSTMM, BSAM, the SDR‑pentest lineage and a deep body of research came first; RFSAM organises that landscape into something you can navigate by. For Bluetooth at the link layer and above it defers to [Tarlogic's BSAM](https://www.tarlogic.com/bsam/) rather than duplicating it. ## The model -Controls are indexed on two axes — **protocol** and **layer**. The layer axis is a descent from spectrum down to application: +Controls are indexed on two axes: **protocol** and **layer**. The layer axis is a descent from spectrum down to application: | | layer | what it asks | |---|---|---| @@ -20,7 +20,7 @@ Controls are indexed on two axes — **protocol** and **layer**. The layer axis | `AT` | Attack | injection, replay, hijack, rogue infrastructure | | `AP` | Application | what the device trusts above the link | -Control IDs follow `RFSAM---` (e.g. `RFSAM-BLE-AT-01`). The protocol and layer segments must match the control's fields — this is enforced in validation. +Control IDs follow `RFSAM---` (e.g. `RFSAM-BLE-AT-01`). The protocol and layer segments must match the control's fields; this is enforced in validation. Each control carries a `reviewStatus`: **stub** (migrated outline), **draft** (researched and cited, awaiting review), or **verified** (checked). Every nontrivial claim cites a source; uncertain claims are flagged inline for review. @@ -56,4 +56,4 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for the control schema, the ID/layer rule ## License -The methodology content is licensed **CC BY‑SA 4.0** — see [LICENSE](LICENSE). Reuse and adapt it with attribution to Electronic Cats, sharing derivatives under the same license. +The methodology content is licensed **CC BY‑SA 4.0**, see [LICENSE](LICENSE). Reuse and adapt it with attribution to Electronic Cats, sharing derivatives under the same license. diff --git a/WAYFINDER-AUTHORING.md b/WAYFINDER-AUTHORING.md index 2a607b4..8da2e04 100644 --- a/WAYFINDER-AUTHORING.md +++ b/WAYFINDER-AUTHORING.md @@ -1,12 +1,12 @@ # Wayfinder authoring rules -How to add or extend a technology's wayfinder — the per-protocol page that walks a +How to add or extend a technology's wayfinder: the per-protocol page that walks a researcher down the assessment descent and hands them the **kit** (hardware + software) for what they want to do. BLE is the reference implementation; copy its shape. Each technology is two files: -- **`src/data/toolchains/.js`** — its descent and tooling: `export default { "status":"complete", "facts":[…], "reference":…, "layers":{…} }` (a JSON object literal — valid JS, so double-quote keys/strings, no trailing commas, no comments). -- **`src/data/protocol-tools/.json`** — the new tools that protocol introduces (a JSON array). `scripts/seed-tools.mjs` folds every `protocol-tools/*.json` into the catalogue automatically. +- **`src/data/toolchains/.js`**, its descent and tooling: `export default { "status":"complete", "facts":[…], "reference":…, "layers":{…} }` (a JSON object literal, valid JS, so double-quote keys/strings, no trailing commas, no comments). +- **`src/data/protocol-tools/.json`**, the new tools that protocol introduces (a JSON array). `scripts/seed-tools.mjs` folds every `protocol-tools/*.json` into the catalogue automatically. Wire the toolchain in via one line in **`src/data/toolchains.js`** (`import from './toolchains/.js'` + `: ,`). BLE and Wi-Fi live inline in that file as the reference. Rendered by `src/pages/wayfinder/[protocol].astro`. Validated by `npm run validate`. @@ -38,7 +38,7 @@ Write content under the **layer** keys; the page maps them to the steps above. 2. **Every software node bonds to the hardware (or input) it depends on. Nothing floats.** You cannot run Sniffle without a CC1352 board; you cannot run ice9 without an SDR. Express it as `{ tool: 'sniffle', deps: ['catsniffer'] }`. A software bubble with no - `deps` (and no `needs`) is a bug — unless the tool *is* the radio (rare). + `deps` (and no `needs`) is a bug, unless the tool *is* the radio (rare). 3. **The decoder is the entry: step → decoder → software → hardware.** When a step has a `decoder` (e.g. `decoder: 'wireshark'`), it renders as the **first node connected to the @@ -53,46 +53,46 @@ Write content under the **layer** keys; the page maps them to the steps above. 5. **Software-led where the user picks a technique** (Capture, Attack, Spectrum): the bubble is the software/technique and the radio is its `deps`. For BLE *every* capture/attack tool - is software-led — even the radio-native Ubertooth goes through its host software + is software-led: even the radio-native Ubertooth goes through its host software (`ubertooth-tools` → `ubertooth-one`) rather than appearing as a bare radio. Only use a hardware bubble as the primary when there genuinely is no software layer. 6. **Every `tool` and `dep` slug must exist in the tools catalogue** (`seed-tools.mjs`), and every catalogue entry must have a **verified** `repo` or `homepage`. **NEVER invent a URL.** Verify it first: `gh api repos//` or a web search. If you can't verify a tool - or a claim, leave it out or flag it — see `[[no-unverified-claims]]`. + or a claim, leave it out or flag it; see `[[no-unverified-claims]]`. -7. **`facts` per protocol** — band, channels, modulation, range, versions. Verified, concise. +7. **`facts` per protocol**: band, channels, modulation, range, versions. Verified, concise. Shown at the top of the kit panel. (See BLE's `facts` array.) -8. **`lookFor` on the Identify step** — a short list of "common things to check on any +8. **`lookFor` on the Identify step**: a short list of "common things to check on any device" (chipset/CVEs, version, identifiers, security mode, etc.). 9. **Intents are a soft lens, never a cage.** They highlight relevant steps and filter the kit; "Everything" is the default and nothing is ever hidden. Don't add per-protocol - intents — the six are shared. + intents; the six are shared. -10. **`reference`** — if an established methodology owns a layer for this tech (BSAM owns +10. **`reference`**: if an established methodology owns a layer for this tech (BSAM owns BLE's link-and-above), set `reference: { name, url, note }`. Otherwise `null`. --- ## Schemas -**Tool catalogue** — `scripts/seed-tools.mjs`: +**Tool catalogue** (`scripts/seed-tools.mjs`): ```js { slug, name, vendor, type: 'hardware' | 'software' | 'project', protocols: [...], note, // one or two sentences - spec?, // e.g. SDR bandwidth/tuning range — shown as a mono line + spec?, // e.g. SDR bandwidth/tuning range, shown as a mono line repo? | homepage?, // VERIFIED url software?: [slugs], // (for hardware) what runs on it, shown on the tool's own page } ``` -**Toolchain** — `src/data/toolchains.js`: +**Toolchain** (`src/data/toolchains.js`): ```js PROTOCOL: { status: 'complete' | 'planned', @@ -110,7 +110,7 @@ PROTOCOL: { **A tool entry inside a layer's `tools`:** ```js { - tool, // slug — the bubble (coloured by its catalogue type) + tool, // slug: the bubble (coloured by its catalogue type) deps?: [slugs], // the hardware it runs on / the input it consumes (rule 2) role?, // short label, e.g. 'Primary sniffer' why?, // one sentence on when/why to pick it @@ -123,7 +123,7 @@ PROTOCOL: { ## How to add a protocol -1. **Research the toolchain** for the technology — the real hardware and software at each +1. **Research the toolchain** for the technology: the real hardware and software at each step, and the reasons to pick each. Verify every repo/homepage (rule 6) and every technical fact (rule 7). 2. **Write the new tools** into `src/data/protocol-tools/.json` (a JSON array; reuse @@ -132,7 +132,7 @@ PROTOCOL: { following the six steps and the ten rules. Set `status: "complete"`. 4. **Wire it in**: add `import from './toolchains/.js';` and `: ,` to `src/data/toolchains.js`. -5. **`node scripts/seed-tools.mjs && npm run validate && npm run build`** — all must pass +5. **`node scripts/seed-tools.mjs && npm run validate && npm run build`**: all must pass (the validator checks every slug, dep and decoder resolves). 5. Open the page at `/wayfinder/` and confirm the pipeline reads correctly. diff --git a/src/components/DefersToBsam.astro b/src/components/DefersToBsam.astro index ec4c81f..5a0946f 100644 --- a/src/components/DefersToBsam.astro +++ b/src/components/DefersToBsam.astro @@ -2,7 +2,7 @@ import { bsam } from '../data/bsam.js'; const { ids, deferred } = Astro.props; const note = deferred - ? 'This layer is covered by BSAM. RFSAM does not duplicate it — run these BSAM controls and carry the result into the RF assessment flow.' + ? 'This layer is covered by BSAM. RFSAM does not duplicate it, run these BSAM controls and carry the result into the RF assessment flow.' : 'For the link-layer judgement, RFSAM defers to these BSAM controls. RFSAM’s role here is the RF capture that gets you to the point where they apply.'; --- {ids?.length > 0 && ( diff --git a/src/components/References.astro b/src/components/References.astro index bfe9808..bbcca3f 100644 --- a/src/components/References.astro +++ b/src/components/References.astro @@ -7,7 +7,7 @@ const { references } = Astro.props;
  • [{r.key}]
    {r.title} - — {[r.authors, r.venue, r.year].filter(Boolean).join(', ')} ({r.type}) + , {[r.authors, r.venue, r.year].filter(Boolean).join(', ')} ({r.type})
  • ))} diff --git a/src/content/controls/_template.md b/src/content/controls/_template.md index 904a68d..03e695f 100644 --- a/src/content/controls/_template.md +++ b/src/content/controls/_template.md @@ -41,7 +41,7 @@ lastResearched: 2026-01-01 How the RF/protocol works and why this control matters. Every nontrivial claim cites a `references[]` entry. Mark anything unverified with: -> [!FLAG] claim — what still needs to be checked +> [!FLAG] claim, what still needs to be checked ## Procedure diff --git a/src/content/controls/rfsam-adsb-ll-01.md b/src/content/controls/rfsam-adsb-ll-01.md index fe03436..e3f3f19 100644 --- a/src/content/controls/rfsam-adsb-ll-01.md +++ b/src/content/controls/rfsam-adsb-ll-01.md @@ -11,14 +11,14 @@ applicability: deferred: false objective: >- Determine what authenticity guarantees the ADS-B link provides for a received - frame — whether a receiver can prove a DF17/DF18 Extended Squitter came from + frame, whether a receiver can prove a DF17/DF18 Extended Squitter came from the aircraft whose ICAO address, callsign and position it carries, and whether the frame is protected against modification or replay. intro: >- ADS-B is an unauthenticated, unencrypted broadcast: the 24-bit CRC on each 1090ES frame is an error-detecting checksum, not a cryptographic signature, so a receiver cannot tell a genuine aircraft from a well-formed forgery. This - control verifies that absence directly — it characterises the link's authenticity + control verifies that absence directly, it characterises the link's authenticity (none) and is the assessment that justifies the spoofing/injection findings at the Attack layer. prerequisites: @@ -28,7 +28,7 @@ prerequisites: - 'A 1090ES decoder (dump1090 or readsb) plus pyModeS to interpret the raw frame fields and confirm there is no authentication element' signal: freq: '1090 MHz (Mode S Extended Squitter / 1090ES, worldwide); 978 MHz UAT additionally in the US for lower-altitude general aviation' - bandwidth: '~2 MHz (the decoder typically samples 2–2.4 MS/s)' + bandwidth: '~2 MHz (the decoder typically samples 2 to 2.4 MS/s)' modulation: 'Pulse-Position Modulation (PPM) at 1 Mbps; a 112-bit Extended Squitter (8 µs preamble + 112 µs data)' skill: intermediate attacks: @@ -47,7 +47,7 @@ attacks: power. summary: >- The link provides no authenticity, so forging an Extended Squitter is - sufficient to impersonate an aircraft — the defining ADS-B weakness this + sufficient to impersonate an aircraft, the defining ADS-B weakness this control assesses. - name: Message modification and deletion refs: @@ -114,15 +114,15 @@ lastResearched: 2026-06-14 --- ## Mechanism -ADS-B "out" rides the Mode S downlink as a 112-bit Extended Squitter, transmitted as 1 Mbps pulse-position modulation on 1090 MHz (DF17 from transponder-equipped aircraft, DF18 for TIS-B / non-transponder sources) [icao9871]. Each frame carries the 24-bit ICAO aircraft address, a type code, and the payload it implies — callsign, CPR-encoded position, or velocity. The defining property for an auditor is that *none of these fields is authenticated*: the protocol has no signature over the message, no message authentication code, no sequence number and no replay protection [strohmeier2014security]. The trailing 24 bits are a CRC computed over the message; it is an error-detecting checksum (and, in Mode S, an address overlay), **not** a cryptographic integrity check, so anyone can recompute it for a forged frame [icao9871][strohmeier2014security]. +ADS-B "out" rides the Mode S downlink as a 112-bit Extended Squitter, transmitted as 1 Mbps pulse-position modulation on 1090 MHz (DF17 from transponder-equipped aircraft, DF18 for TIS-B / non-transponder sources) [icao9871]. Each frame carries the 24-bit ICAO aircraft address, a type code, and the payload it implies, callsign, CPR-encoded position, or velocity. The defining property for an auditor is that *none of these fields is authenticated*: the protocol has no signature over the message, no message authentication code, no sequence number and no replay protection [strohmeier2014security]. The trailing 24 bits are a CRC computed over the message; it is an error-detecting checksum (and, in Mode S, an address overlay), **not** a cryptographic integrity check, so anyone can recompute it for a forged frame [icao9871][strohmeier2014security]. -The consequence is that "authenticity assessment" at the link layer has a known answer — the link provides none — and the control's job is to confirm and characterise that for the specific target deployment. The academic and practical literature established this directly: Costin and Francillon built an SDR receive/transmit chain in GNU Radio and demonstrated that injecting forged ADS-B is practical for a moderately capable attacker [costin2012ghost]; Schäfer, Lenders and Martinovic experimentally analysed message **injection, modification and deletion** against ADS-B and confirmed the absence of any link-layer defence against them [schaefer2013experimental]; the Strohmeier survey synthesises the gap and the proposed (non-cryptographic) countermeasures such as multilateration and plausibility checking [strohmeier2014security][strohmeier2014realities]. +The consequence is that "authenticity assessment" at the link layer has a known answer, the link provides none, and the control's job is to confirm and characterise that for the specific target deployment. The academic and practical literature established this directly: Costin and Francillon built an SDR receive/transmit chain in GNU Radio and demonstrated that injecting forged ADS-B is practical for a moderately capable attacker [costin2012ghost]; Schäfer, Lenders and Martinovic experimentally analysed message **injection, modification and deletion** against ADS-B and confirmed the absence of any link-layer defence against them [schaefer2013experimental]; the Strohmeier survey synthesises the gap and the proposed (non-cryptographic) countermeasures such as multilateration and plausibility checking [strohmeier2014security][strohmeier2014realities]. -Two named attack families follow from this missing authenticity. **Injection / spoofing** — transmit a well-formed, CRC-valid Extended Squitter with a chosen ICAO address and position, and receivers accept a ghost aircraft or a moved track [costin2012ghost][schaefer2013experimental]. **Modification and deletion** — overshadow or selectively jam genuine squitters to corrupt or remove specific aircraft, since there is no integrity or completeness guarantee [schaefer2013experimental][strohmeier2014security]. This control assesses the link's (lack of) authenticity; the active transmit-side exploitation is the Attack-layer control (RFSAM-ADSB-AT-01) and is legally sensitive — see Remediation and the authorised-testing note there. +Two named attack families follow from this missing authenticity. **Injection / spoofing**, transmit a well-formed, CRC-valid Extended Squitter with a chosen ICAO address and position, and receivers accept a ghost aircraft or a moved track [costin2012ghost][schaefer2013experimental]. **Modification and deletion**, overshadow or selectively jam genuine squitters to corrupt or remove specific aircraft, since there is no integrity or completeness guarantee [schaefer2013experimental][strohmeier2014security]. This control assesses the link's (lack of) authenticity; the active transmit-side exploitation is the Attack-layer control (RFSAM-ADSB-AT-01) and is legally sensitive, see Remediation and the authorised-testing note there. ## Procedure -Receiving and decoding ADS-B is passive and generally lawful; the steps below are receive-only. Do **not** transmit on 1090 MHz outside an authorised, RF-contained (conducted or shielded) setup — that is the Attack-layer control, not this one. +Receiving and decoding ADS-B is passive and generally lawful; the steps below are receive-only. Do **not** transmit on 1090 MHz outside an authorised, RF-contained (conducted or shielded) setup, that is the Attack-layer control, not this one. 1. Confirm the band is alive and capture is clean. Tune a receive-only SDR to 1090 MHz and start the reference decoder; for a portable capture record raw I/Q first and log overflow counters (RFSAM-RES-01). ```bash @@ -140,21 +140,21 @@ Receiving and decoding ADS-B is passive and generally lawful; the steps below ar ```bash python3 -c "import pyModeS as pms; m='8D40621D58C382D690C8AC2863A7'; print('DF', pms.df(m)); print('ICAO', pms.adsb.icao(m)); print('typecode', pms.adsb.typecode(m)); print('CRC residual', pms.crc(m))" ``` - Expected: `DF 17`, `ICAO 40621d`, a type code, and a CRC residual of `0` for an intact frame. The point of the step is what is *absent* — there is no signature, MAC, nonce or sequence field anywhere in the 112 bits; the only integrity element is the CRC, which any transmitter can compute [strohmeier2014security][icao9871]. + Expected: `DF 17`, `ICAO 40621d`, a type code, and a CRC residual of `0` for an intact frame. The point of the step is what is *absent*, there is no signature, MAC, nonce or sequence field anywhere in the 112 bits; the only integrity element is the CRC, which any transmitter can compute [strohmeier2014security][icao9871]. 4. Demonstrate that the CRC offers no authenticity. Recompute the CRC over a *modified* message body (e.g. flip the callsign or position bits) and show it is trivially made valid again, proving the checksum binds nothing to the real sender. ```bash python3 -c "import pyModeS as pms; m='8D40621D58C382D690C8AC2863A7'; body=m[:-6]; print('forged-valid frame:', body + format(pms.crc(body + '000000', encode=True), '06X'))" ``` - Expected: a new 28-hex-character frame whose CRC residual is `0` despite carrying an attacker-chosen body — the concrete evidence that the link provides integrity-of-transmission detection only, not authenticity of origin. (This is a local computation on captured/synthetic data; it transmits nothing.) + Expected: a new 28-hex-character frame whose CRC residual is `0` despite carrying an attacker-chosen body, the concrete evidence that the link provides integrity-of-transmission detection only, not authenticity of origin. (This is a local computation on captured/synthetic data; it transmits nothing.) -5. Record the finding for the target deployment: which link (1090ES vs 978 UAT), which message types and identifiers are exposed in clear, and the confirmation that no field authenticates the originator. Note what downstream system trusts the feed (tracking display, aggregator, TCAS-style logic) — that scopes the impact of a spoof. +5. Record the finding for the target deployment: which link (1090ES vs 978 UAT), which message types and identifiers are exposed in clear, and the confirmation that no field authenticates the originator. Note what downstream system trusts the feed (tracking display, aggregator, TCAS-style logic), that scopes the impact of a spoof. ## Field case A representative bench walk-through using a single RTL-SDR V4 on a quarter-wave 1090 MHz whip indoors near a window. `dump1090 --net` decoded local traffic within a few seconds; capturing ~5 minutes of Beast output yielded several hundred DF17 frames across roughly [FILL: number of distinct ICAO addresses observed] aircraft. -Taking one captured airborne-position frame `8D40621D58C382D690C8AC2863A7`, pyModeS reported `DF 17`, ICAO `40621d`, an airborne-position type code, and CRC residual `0`. Re-running step 4 against a body with a deliberately altered position produced a *different* 28-hex frame that still computed to CRC residual `0`. That is the whole finding made tangible: the receiver's only integrity element validated an attacker-chosen payload exactly as readily as the genuine one, because the CRC binds the message to itself, not to the aircraft. No transmission occurred — the forged frame existed only as a hex string in the analysis, never on the air. +Taking one captured airborne-position frame `8D40621D58C382D690C8AC2863A7`, pyModeS reported `DF 17`, ICAO `40621d`, an airborne-position type code, and CRC residual `0`. Re-running step 4 against a body with a deliberately altered position produced a *different* 28-hex frame that still computed to CRC residual `0`. That is the whole finding made tangible: the receiver's only integrity element validated an attacker-chosen payload exactly as readily as the genuine one, because the CRC binds the message to itself, not to the aircraft. No transmission occurred, the forged frame existed only as a hex string in the analysis, never on the air. The decoded ICAO `40621d` and the frame `8D40621D58C382D690C8AC2863A7` are the standard ADS-B airborne-position documentation example (DF17, type code 11), used here as a reproducible decode rather than measured local traffic; the bracketed aircraft count is left as a [FILL: number of distinct ICAO addresses observed] placeholder for the operator's own capture and must not be presented as a measured result. @@ -162,10 +162,10 @@ The decoded ICAO `40621d` and the frame `8D40621D58C382D690C8AC2863A7` are the s ADS-B authenticity cannot be added at the link layer without changing the standard, so remediation is about *detecting* forgeries and *not over-trusting* the feed rather than cryptographically securing it [strohmeier2014security][strohmeier2014realities]. -- **Developer (decoder / receiver software):** never treat a CRC-valid frame as a trusted one. Implement plausibility checks on the decoded stream — physically impossible kinematics (jumps, impossible speeds/climb rates), positions inconsistent with the receiver's own range/antenna geometry, and ICAO addresses that should not be airborne or that appear from impossible directions [strohmeier2014security]. Expose a confidence/anomaly flag rather than a binary "valid". +- **Developer (decoder / receiver software):** never treat a CRC-valid frame as a trusted one. Implement plausibility checks on the decoded stream, physically impossible kinematics (jumps, impossible speeds/climb rates), positions inconsistent with the receiver's own range/antenna geometry, and ICAO addresses that should not be airborne or that appear from impossible directions [strohmeier2014security]. Expose a confidence/anomaly flag rather than a binary "valid". - **Integrator (system fusing the feed):** corroborate ADS-B against an independent source before acting on it. Cross-receiver multilateration (MLAT) times the same frame at several stations to fix an aircraft independently of what it claims; fuse with primary/secondary radar where available. Do not let a single unauthenticated broadcast drive a safety- or security-relevant decision [strohmeier2014realities]. - **Operator / asset owner:** monitor for spoofing patterns (sudden ghost tracks, duplicated or implausible ICAO addresses, tracks that appear only at one receiver) and have a procedure for when the picture is untrustworthy. Treat any control or display that ingests ADS-B as consuming untrusted input. -- **Note on active testing:** validating the injection side (RFSAM-ADSB-AT-01) means transmitting on 1090 MHz, which is protected aviation safety spectrum that affects real air-traffic systems. Do this **only** as authorised lab/research work over a conducted (cabled) or shielded (Faraday-enclosure) path into your own receiver, with explicit permission — never radiate on-air under any circumstances. This control's own procedure stays receive-only and computes forgeries offline. +- **Note on active testing:** validating the injection side (RFSAM-ADSB-AT-01) means transmitting on 1090 MHz, which is protected aviation safety spectrum that affects real air-traffic systems. Do this **only** as authorised lab/research work over a conducted (cabled) or shielded (Faraday-enclosure) path into your own receiver, with explicit permission, never radiate on-air under any circumstances. This control's own procedure stays receive-only and computes forgeries offline. diff --git a/src/content/controls/rfsam-adsb-phy-01.md b/src/content/controls/rfsam-adsb-phy-01.md index a382899..e659986 100644 --- a/src/content/controls/rfsam-adsb-phy-01.md +++ b/src/content/controls/rfsam-adsb-phy-01.md @@ -11,15 +11,15 @@ applicability: deferred: false objective: >- Determine whether the target's ADS-B transmissions can be received and decoded - from the air with a low-cost SDR — recovering the 24-bit ICAO address, callsign, - CPR-encoded position and velocity from DF17/DF18 Extended Squitter frames — which + from the air with a low-cost SDR, recovering the 24-bit ICAO address, callsign, + CPR-encoded position and velocity from DF17/DF18 Extended Squitter frames, which establishes the capture baseline every downstream plausibility and spoofing assessment depends on. intro: >- ADS-B is a one-way, unencrypted, unauthenticated broadcast: there is nothing to decrypt, only a public waveform to receive and decode. This PHY control verifies - the capture baseline — demodulating the 1 Mbps pulse-position waveform and reading - out the 112-bit Extended Squitter — that the spectrum, attack and air-picture + the capture baseline, demodulating the 1 Mbps pulse-position waveform and reading + out the 112-bit Extended Squitter, that the spectrum, attack and air-picture controls all build on. It is observational; forging frames is assessed separately at the Attack layer. prerequisites: @@ -39,7 +39,7 @@ attacks: - strohmeier2013survey impact: >- Full recovery of every transmitting aircraft's identity (ICAO address, - callsign), position and velocity in the clear — supports tracking, targeting + callsign), position and velocity in the clear, supports tracking, targeting and reconnaissance, and is the prerequisite observation step for any active spoofing. preconditions: A receive-capable SDR within radio range of the transmitter; no keys, no association. @@ -53,7 +53,7 @@ attacks: - strohmeier2017perception impact: >- Injection of non-existent ('ghost') aircraft, modification of an existing - track, or flooding of the air picture — every receiver in range accepts a + track, or flooding of the air picture, every receiver in range accepts a well-formed 1090ES frame as a genuine aircraft. preconditions: >- A TX-capable SDR and the ability to emit a well-formed higher-power 1090ES @@ -118,7 +118,7 @@ lastResearched: 2026-06-14 ## Mechanism ADS-B 'out' is a periodic, one-way broadcast in which an aircraft reports its own -state — identity, position, velocity — with no interrogation, no association, no +state, identity, position, velocity, with no interrogation, no association, no encryption and no authentication [costin2012ghost][strohmeier2013survey]. Worldwide it rides the 1090 MHz Mode S Extended Squitter (1090ES); in the US, lower-altitude general aviation additionally uses a separate 978 MHz UAT link [strohmeier2017perception]. @@ -134,7 +134,7 @@ a 272-bit long message [sun2021riddle]. The 112-bit frame begins with a 5-bit downlink format. ADS-B uses **DF17** for transponder-equipped aircraft and **DF18** for non-transponder / TIS-B transmitters; it then carries the 24-bit ICAO aircraft address and a 5-bit type code that selects -the payload — aircraft identification (the 8-character callsign), airborne or surface +the payload, aircraft identification (the 8-character callsign), airborne or surface position (latitude/longitude in Compact Position Reporting, CPR, encoding), or velocity [sun2021riddle]. A 24-bit parity field lets a receiver validate the frame. Crucially, **none of the identifiers is authenticated**: the ICAO address, callsign @@ -142,7 +142,7 @@ and CPR position are broadcast in the clear with no signature and no integrity o the source, so a receiver cannot tell a genuine aircraft from a forged one [costin2012ghost][strohmeier2013survey]. -This control verifies only the **receive-and-decode** baseline — the passive +This control verifies only the **receive-and-decode** baseline, the passive eavesdropping that the literature established is trivially feasible with a cheap SDR [costin2012ghost]. That same absent authentication is what makes the active attack families possible: experimental work has demonstrated message injection ('ghost @@ -154,7 +154,7 @@ the Attack-layer control, not here; this PHY control stays receive-only. ## Procedure > Receive-only throughout. Capturing and decoding ADS-B is passive and generally -> lawful, but transmitting on 1090/978 MHz is not — do not transmit at any step here. +> lawful, but transmitting on 1090/978 MHz is not, do not transmit at any step here. 1. Confirm the band is alive before committing a decoder. Tune an SDR to 1090 MHz in a waterfall viewer and watch for the short, bursty Extended-Squitter pulses (ADS-B @@ -184,7 +184,7 @@ the Attack-layer control, not here; this PHY control stays receive-only. readsb --device-type rtlsdr --net --write-json /run/readsb ``` Expected: readsb starts, tracks many aircraft at once, and serves a JSON - `aircraft.json` (consumed by a map such as tar1090) plus Beast/raw ports — the + `aircraft.json` (consumed by a map such as tar1090) plus Beast/raw ports, the handoff point to the Application-layer air-picture and plausibility controls. 4. (US only) Add the 978 MHz UAT link. The 1090 decoders do not cover UAT; tune a @@ -195,13 +195,13 @@ the Attack-layer control, not here; this PHY control stays receive-only. Expected: UAT downlink frames from lower-altitude general aviation, merged into the same aircraft picture. -5. Verify decode correctness on individual frames with pyModeS — the decode you can +5. Verify decode correctness on individual frames with pyModeS, the decode you can reason about by hand. Feed a hex frame to the CLI: ```bash modes decode 8D406B902015A678D4D220AA4BDA ``` Expected: `df 17`, `icao 406B90`, `typecode 4` (identification), callsign - `EZY85MH` — confirming the demodulated bits decode to a sensible identity. This is + `EZY85MH`, confirming the demodulated bits decode to a sensible identity. This is the per-frame ground truth behind the live table. 6. (Optional) Demodulate inside a flowgraph instead of a black-box decoder, when you @@ -236,22 +236,22 @@ modes decode 8D40058B58C901375147EFD09357 --reference 49.0 6.0 These are the canonical pyModeS test vectors, so the expected outputs are stable: a `40058B` position near the 49.0 N, 6.0 E reference and the `406B90` / `EZY85MH` -identity. This is the verifiable, reproducible core of the field case — the decode +identity. This is the verifiable, reproducible core of the field case, the decode chain confirmed against fixed, published frames, with no air capture or transmitter required. -Illustrative walkthrough — substitute the values you capture: on a real over-the-air +Illustrative walkthrough, substitute the values you capture: on a real over-the-air session you would replace these vectors with live frames from step 2/3 and record the receiver-side numbers for the local environment. No author-measured live ADS-B capture -is recorded here; the representative over-the-air figures — distinct aircraft seen over +is recorded here; the representative over-the-air figures, distinct aircraft seen over a session, fraction of frames passing parity, maximum range with/without a 1090 MHz -LNA+filter — are [FILL: measured receiver statistics], to be filled from an authorised +LNA+filter, are [FILL: measured receiver statistics], to be filled from an authorised on-site capture. ## Remediation -ADS-B's exposure is architectural — the link is plaintext and unauthenticated by -design [costin2012ghost][strohmeier2013survey] — so "remediation" at this layer is +ADS-B's exposure is architectural, the link is plaintext and unauthenticated by +design [costin2012ghost][strohmeier2013survey], so "remediation" at this layer is about not over-trusting the feed rather than securing the radio. - **Developer (avionics / receiver firmware):** do not treat a decoded DF17/DF18 @@ -264,12 +264,12 @@ about not over-trusting the feed rather than securing the radio. - **Integrator (tracking / display / fusion systems):** never rely on ADS-B as a sole source of truth. Fuse it with independent sensors (primary/secondary radar, multilateration that times the same frame at several stations to fix an aircraft - independently of what it claims) and run plausibility checks — impossible + independently of what it claims) and run plausibility checks, impossible kinematics, positions inconsistent across receivers, ICAO addresses that should not be airborne [schafer2013experimental][strohmeier2017perception]. These detections are implemented at the Application layer; this PHY capture is their input. -- **Operator (researcher / SOC running a receiver):** keep receive-only — capturing +- **Operator (researcher / SOC running a receiver):** keep receive-only, capturing and decoding ADS-B is passive and generally lawful, but transmitting on 1090/978 MHz is protected aviation safety spectrum and must never be radiated; any spoofing/ injection assessment belongs to the Attack-layer control and is done only on diff --git a/src/content/controls/rfsam-ble-at-01.md b/src/content/controls/rfsam-ble-at-01.md index 0b9f2bc..739819d 100644 --- a/src/content/controls/rfsam-ble-at-01.md +++ b/src/content/controls/rfsam-ble-at-01.md @@ -7,14 +7,14 @@ criticality: critical applicability: - BLE objective: >- - Determine whether an established BLE connection can be followed and taken over — - by jam-and-hijack, packet injection, or reconnection spoofing — giving an + Determine whether an established BLE connection can be followed and taken over, + by jam-and-hijack, packet injection, or reconnection spoofing, giving an attacker control of the peripheral or a man-in-the-middle position. intro: >- An unencrypted BLE connection can be taken over: the attacker follows the connection's channel hopping, then transmits as the master, evicting the legitimate central and gaining full control of the peripheral. RFSAM owns the - PHY-layer prerequisite — following the hop sequence well enough to inject — + PHY-layer prerequisite, following the hop sequence well enough to inject, while the link-layer injection and forced-disconnection findings are assessed under BSAM (BSAM-AP-06, BSAM-AU-03, BSAM-EN-01). prerequisites: @@ -23,7 +23,7 @@ prerequisites: software: - 'Btlejack, Sniffle, or the InjectaBLE firmware/tooling' signal: - freq: '2.402–2.480 GHz (40 channels, 2 MHz spacing)' + freq: '2.402 to 2.480 GHz (40 channels, 2 MHz spacing)' bandwidth: '2 MHz per channel' modulation: 'GFSK (LE 1M / 2M PHY)' skill: advanced @@ -81,7 +81,7 @@ references: url: 'https://nvd.nist.gov/vuln/detail/CVE-2020-9770' type: cve - key: cauquil2018btlejack - title: Btlejack — BLE sniffing, jamming and hijacking tool + title: Btlejack, BLE sniffing, jamming and hijacking tool authors: D. Cauquil (virtualabs) venue: DEF CON 26 year: 2018 @@ -116,8 +116,8 @@ Three families of takeover are documented in the literature. **Jam-and-hijack** ## Field case -Against the ELK-BLEDOM LED controller: sniffing the vendor app setting a colour revealed handle 0x000E with format 7e 07 05 RR GG BB 10 ef. After hijacking the live connection (DATA→CENTRAL), writing `w 0x000e 7e 07 05 03 ff 00 00 10 ef` drove the strip to the attacker's colour. The same technique applies unchanged to locks and medical devices — the LED strip is merely the harmless, vivid demonstration. A real implementation detail: the decoder's current Access Address must be set to the connection AA only after reaching CENTRAL (with a flush first), because advertisements seen during INITIATING reset it to the advertising AA and silently break data-PDU decoding. +Against the ELK-BLEDOM LED controller: sniffing the vendor app setting a colour revealed handle 0x000E with format 7e 07 05 RR GG BB 10 ef. After hijacking the live connection (DATA→CENTRAL), writing `w 0x000e 7e 07 05 03 ff 00 00 10 ef` drove the strip to the attacker's colour. The same technique applies unchanged to locks and medical devices, the LED strip is merely the harmless, vivid demonstration. A real implementation detail: the decoder's current Access Address must be set to the connection AA only after reaching CENTRAL (with a flush first), because advertisements seen during INITIATING reset it to the advertising AA and silently break data-PDU decoding. ## Remediation -Encrypt the link with LE Secure Connections — the InjectaBLE authors recommend exactly this as the primary countermeasure (LESC pairing with authentication and 128-bit keys), and it is the strongest single mitigation here. Note the precise effect: the timing-based injection itself is inherent to the BLE specification and is not stopped by encryption, but on an encrypted link any injected data PDU carries no valid MIC and is rejected by the peer, so forged commands and payloads do not take effect (cayre2021injectable). Add application-layer command authentication so a hijacked or injected link still cannot issue trusted commands. Enforce reconnection authentication to close the BLESA class (wu2020blesa). Treat the link as untrusted by default. +Encrypt the link with LE Secure Connections, the InjectaBLE authors recommend exactly this as the primary countermeasure (LESC pairing with authentication and 128-bit keys), and it is the strongest single mitigation here. Note the precise effect: the timing-based injection itself is inherent to the BLE specification and is not stopped by encryption, but on an encrypted link any injected data PDU carries no valid MIC and is rejected by the peer, so forged commands and payloads do not take effect (cayre2021injectable). Add application-layer command authentication so a hijacked or injected link still cannot issue trusted commands. Enforce reconnection authentication to close the BLESA class (wu2020blesa). Treat the link as untrusted by default. diff --git a/src/content/controls/rfsam-ble-cr-01.md b/src/content/controls/rfsam-ble-cr-01.md index 9d4a450..67ef25a 100644 --- a/src/content/controls/rfsam-ble-cr-01.md +++ b/src/content/controls/rfsam-ble-cr-01.md @@ -10,15 +10,15 @@ deferred: true objective: >- Determine which pairing method a BLE link uses (LE Legacy vs LE Secure Connections; Just Works vs authenticated) and, where LE Legacy pairing was - captured, recover the Temporary Key and decrypt the session — establishing + captured, recover the Temporary Key and decrypt the session, establishing whether the link's confidentiality can be broken from a passive capture. intro: >- BLE confidentiality rests entirely on the pairing exchange. LE Legacy pairing (Just Works / 6-digit passkey) derives the session from a low-entropy Temporary Key that is brute-forceable offline from a single captured pairing, and the encryption key size can be negotiated down to 7 bytes. RFSAM owns the - RF-capture prerequisite — sniffing the pairing event well enough to feed a - cracker — while the judgement on pairing mode, legacy-pairing rejection and + RF-capture prerequisite, sniffing the pairing event well enough to feed a + cracker, while the judgement on pairing mode, legacy-pairing rejection and minimum key size is assessed under BSAM (BSAM-PA-01, BSAM-PA-04, BSAM-EN-02, BSAM-EN-03). prerequisites: @@ -27,7 +27,7 @@ prerequisites: software: - 'Sniffle / nRF Sniffer / Ubertooth for capture, Wireshark to export the PCAP, and crackle to brute-force the LE Legacy TK and decrypt' signal: - freq: '2.402–2.480 GHz (40 × 2 MHz channels: 3 advertising 37/38/39 + 37 data; a connection hops every event)' + freq: '2.402 to 2.480 GHz (40 × 2 MHz channels: 3 advertising 37/38/39 + 37 data; a connection hops every event)' bandwidth: '2 MHz per channel' modulation: 'GFSK (LE 1M / 2M / Coded PHY)' skill: advanced @@ -44,7 +44,7 @@ attacks: with LE Legacy (not LE Secure Connections / ECDH). summary: >- LE Legacy pairing derives the session from a 128-bit TK that is 0 for Just - Works and a 6-digit value (≤ 999999) for passkey — both brute-forceable + Works and a 6-digit value (≤ 999999) for passkey, both brute-forceable offline, after which the session is decrypted. The canonical BLE-pairing weakness and the reference method for this control. - name: KNOB on BLE (key-size entropy downgrade) @@ -81,7 +81,7 @@ attacks: out-of-order encryption request. summary: >- An implementation flaw that installs a zero LTK on an out-of-order - link-layer encryption request during Secure Connections pairing — a + link-layer encryption request during Secure Connections pairing, a reminder that even LESC is only as strong as the SoC's SMP state machine. references: - key: ryan2013woot @@ -145,9 +145,9 @@ lastResearched: 2026-06-14 BLE confidentiality is decided entirely at pairing. Two regimes exist: **LE Legacy** pairing (4.0/4.1, still selectable on later devices) and **LE Secure Connections** (LESC, added in 4.2). They differ in how the key that protects the session is established, and that difference is the whole of this control. -In **LE Legacy** pairing the link is bootstrapped from a 128-bit **Temporary Key (TK)**. For *Just Works* the TK is fixed at zero; for the *6-digit passkey* method the TK is the passkey value, so at most 999999 — about 20 bits of entropy [ryan2013woot]. From the TK and the random/confirm values exchanged in the pairing packets, the Short Term Key and then the Long Term Key are derived. Because every input except the TK is sent in the clear, an observer who captured the pairing exchange can brute-force the TK offline, rederive the keys, and decrypt the whole session — the method Mike Ryan published with the `crackle` tool [ryan2013woot]. LESC replaces this with an Elliptic-Curve Diffie–Hellman (P-256) key agreement, so the session key is never derivable from the captured exchange; `crackle` and the LE-Legacy TK brute-force do not apply to it [ryan2013woot]. +In **LE Legacy** pairing the link is bootstrapped from a 128-bit **Temporary Key (TK)**. For *Just Works* the TK is fixed at zero; for the *6-digit passkey* method the TK is the passkey value, so at most 999999, about 20 bits of entropy [ryan2013woot]. From the TK and the random/confirm values exchanged in the pairing packets, the Short Term Key and then the Long Term Key are derived. Because every input except the TK is sent in the clear, an observer who captured the pairing exchange can brute-force the TK offline, rederive the keys, and decrypt the whole session, the method Mike Ryan published with the `crackle` tool [ryan2013woot]. LESC replaces this with an Elliptic-Curve Diffie-Hellman (P-256) key agreement, so the session key is never derivable from the captured exchange; `crackle` and the LE-Legacy TK brute-force do not apply to it [ryan2013woot]. -Two further weaknesses sit beside the legacy-vs-LESC split. The **key-size negotiation** is itself unprotected: the BLE feature/SMP exchange that sets the encryption key size is neither encrypted nor integrity-protected and permits a minimum of 7 bytes, so an attacker impersonating each peer can force both down to 7-byte entropy without violating the spec — the BLE form of the **KNOB** key-negotiation downgrade [antonioli2020knobble]. The KNOB family is tracked under CVE-2019-9506 [cve-2019-9506]; the NVD text is written against Bluetooth BR/EDR, while the BLE applicability — downgrading any BLE long-term and session key to 7-byte entropy — comes from the Antonioli et al. follow-up analysis [antonioli2020knobble], for which no separate CVE was assigned. And even where LESC is selected, the SoC's Security Manager state machine can be flawed: **SweynTooth Zero-LTK Installation** installs an all-zero LTK when an out-of-order encryption request arrives during Secure Connections pairing on affected Telink SDKs, fully bypassing LESC [garbelini2020sweyntooth], tracked as CVE-2019-19194 [cve-2019-19194]. +Two further weaknesses sit beside the legacy-vs-LESC split. The **key-size negotiation** is itself unprotected: the BLE feature/SMP exchange that sets the encryption key size is neither encrypted nor integrity-protected and permits a minimum of 7 bytes, so an attacker impersonating each peer can force both down to 7-byte entropy without violating the spec, the BLE form of the **KNOB** key-negotiation downgrade [antonioli2020knobble]. The KNOB family is tracked under CVE-2019-9506 [cve-2019-9506]; the NVD text is written against Bluetooth BR/EDR, while the BLE applicability, downgrading any BLE long-term and session key to 7-byte entropy, comes from the Antonioli et al. follow-up analysis [antonioli2020knobble], for which no separate CVE was assigned. And even where LESC is selected, the SoC's Security Manager state machine can be flawed: **SweynTooth Zero-LTK Installation** installs an all-zero LTK when an out-of-order encryption request arrives during Secure Connections pairing on affected Telink SDKs, fully bypassing LESC [garbelini2020sweyntooth], tracked as CVE-2019-19194 [cve-2019-19194]. So the security-relevant questions this control answers are: *did the link pair with LE Legacy or LESC; if Legacy, can the session be decrypted from a passive capture; and what key size was negotiated.* The judgement on whether the device **should** have rejected legacy pairing, required interaction, or enforced a key-size floor belongs to BSAM (BSAM-PA-01 device pairing mode, BSAM-PA-04 rejection of legacy pairing, BSAM-EN-02 force use of encryption, BSAM-EN-03 minimum encryption key size); RFSAM supplies only the RF capture that reaches those checks. @@ -159,14 +159,14 @@ So the security-relevant questions this control answers are: *did the link pair ```bash python3 -m sniffle.sniff_receiver -s -e -l -o ble_pairing.pcap ``` - Sniffle follows connections by default (CONN_FOLLOW mode, unless `-a`/`-A` is given), so the connection-following that this capture relies on needs no extra flag; `-e` adds BT5 extended (auxiliary) advertising capture, `-l` enables the long-range (coded) PHY on the primary advertising channels, and `-o` writes the PCAP. Confirm the capture contains the SMP exchange — in Wireshark, filter `btsmp` and look for `Pairing Request` / `Pairing Response`. + Sniffle follows connections by default (CONN_FOLLOW mode, unless `-a`/`-A` is given), so the connection-following that this capture relies on needs no extra flag; `-e` adds BT5 extended (auxiliary) advertising capture, `-l` enables the long-range (coded) PHY on the primary advertising channels, and `-o` writes the PCAP. Confirm the capture contains the SMP exchange, in Wireshark, filter `btsmp` and look for `Pairing Request` / `Pairing Response`. 2. **Read the pairing mode straight from the capture.** In the `Pairing Request`/`Response`, inspect the **AuthReq** flags and the **SC (Secure Connections)** bit: ``` wireshark ble_pairing.pcap # filter: btsmp.opcode == 0x01 || btsmp.opcode == 0x02 ``` - `SC = 0` → **LE Legacy** (crackable below). `SC = 1` → **LE Secure Connections** (ECDH; not crackable from the capture — record it and stop at step 5). Also read the **Maximum Encryption Key Size** field: a value of `7` is the KNOB-relevant floor [antonioli2020knobble]; `16` is full strength. + `SC = 0` → **LE Legacy** (crackable below). `SC = 1` → **LE Secure Connections** (ECDH; not crackable from the capture, record it and stop at step 5). Also read the **Maximum Encryption Key Size** field: a value of `7` is the KNOB-relevant floor [antonioli2020knobble]; `16` is full strength. 3. **Confirm the association model.** From the same packets read **IO Capability** and the **MITM** AuthReq bit. `MITM = 0` with IO `NoInputNoOutput` is *Just Works* (TK = 0). `MITM = 1` with a display/keyboard is *passkey* (TK = the 6-digit value). This tells `crackle` how hard the TK search is. @@ -174,13 +174,13 @@ So the security-relevant questions this control answers are: *did the link pair ```bash crackle -i ble_pairing.pcap ``` - Expected output names the recovered TK/keys, e.g. `TK found: 0` (Just Works) or a 6-digit value (passkey), followed by `LTK found: <16 bytes>`. If it prints `Specify a pcap file with -i` or reports it could not find a complete pairing, the capture is missing packets — re-capture a full exchange. + Expected output names the recovered TK/keys, e.g. `TK found: 0` (Just Works) or a 6-digit value (passkey), followed by `LTK found: <16 bytes>`. If it prints `Specify a pcap file with -i` or reports it could not find a complete pairing, the capture is missing packets, re-capture a full exchange. 5. **Decrypt the session and confirm.** Use the recovered keys to produce a cleartext capture, then verify the decrypted GATT traffic is readable: ```bash crackle -i ble_pairing.pcap -o ble_decrypted.pcap ``` - Open `ble_decrypted.pcap` in Wireshark and confirm post-encryption ATT/GATT operations (e.g. `Write Request`, `Handle Value Notification`) are now in cleartext — that is the proof the link's confidentiality was broken from a passive capture. Enumerating the now-readable GATT table is the hand-off to RFSAM-RES-05 and to the BSAM service-access checks. For LESC captures, record `SC = 1` and the key size and defer the pairing-strength judgement to BSAM-PA/EN with no decryption claim. + Open `ble_decrypted.pcap` in Wireshark and confirm post-encryption ATT/GATT operations (e.g. `Write Request`, `Handle Value Notification`) are now in cleartext, that is the proof the link's confidentiality was broken from a passive capture. Enumerating the now-readable GATT table is the hand-off to RFSAM-RES-05 and to the BSAM service-access checks. For LESC captures, record `SC = 1` and the key size and defer the pairing-strength judgement to BSAM-PA/EN with no decryption claim. ## Field case @@ -190,10 +190,10 @@ A documented public example exercises exactly this control end to end. The crack crackle -i ble_pairing.pcap ``` -against that capture and crackle analyses connection 0 between the link endpoints `08:3e:8e:e1:0b:3e (public)` and `78:c5:e5:6e:dd:e8 (public)`, reports `Found 3 encrypted packets`, brute-forces the TK in `strategy 0, 20 bits of entropy`, and prints `TK found: 000000` — the Just-Works case — followed by `LTK found: 7f62c053f104a5bbe68b1d896a2ed49c` [crackle-tests-01]. Re-running with `-o ble_decrypted.pcap` decrypts the 3 encrypted packets (`Done, processed 713 total packets, decrypted 3`) and dumps a cleartext PCAP, confirming the session was decryptable from the passive capture alone. The same recovered key and the same address pair are independently documented in the project's `tests/02_ltk_decrypt/` fixture, which feeds the value back as `-l 7f62c053f104a5bbe68b1d896a2ed49c` to decrypt the session directly — confirming `7f62c053f104a5bbe68b1d896a2ed49c` as the repository's canonical shipped result [crackle-tests-01]. In your own engagement, the recovered LTK and the connecting device addresses will instead be those of the link you captured. +against that capture and crackle analyses connection 0 between the link endpoints `08:3e:8e:e1:0b:3e (public)` and `78:c5:e5:6e:dd:e8 (public)`, reports `Found 3 encrypted packets`, brute-forces the TK in `strategy 0, 20 bits of entropy`, and prints `TK found: 000000`, the Just-Works case, followed by `LTK found: 7f62c053f104a5bbe68b1d896a2ed49c` [crackle-tests-01]. Re-running with `-o ble_decrypted.pcap` decrypts the 3 encrypted packets (`Done, processed 713 total packets, decrypted 3`) and dumps a cleartext PCAP, confirming the session was decryptable from the passive capture alone. The same recovered key and the same address pair are independently documented in the project's `tests/02_ltk_decrypt/` fixture, which feeds the value back as `-l 7f62c053f104a5bbe68b1d896a2ed49c` to decrypt the session directly, confirming `7f62c053f104a5bbe68b1d896a2ed49c` as the repository's canonical shipped result [crackle-tests-01]. In your own engagement, the recovered LTK and the connecting device addresses will instead be those of the link you captured. ## Remediation -- **Developer (firmware / stack).** Require **LE Secure Connections** and reject LE Legacy pairing for any link carrying sensitive data or control — LESC's ECDH defeats the captured-pairing TK brute-force entirely [ryan2013woot]. Enforce a **minimum encryption key size of 16 bytes** and refuse a negotiated maximum below that, closing the BLE KNOB downgrade [antonioli2020knobble]. Keep the SoC's SMP/Security-Manager up to date and verify it against the SweynTooth class — in particular that it checks pairing state before honouring an encryption request, so a zero LTK can never be installed [garbelini2020sweyntooth]. +- **Developer (firmware / stack).** Require **LE Secure Connections** and reject LE Legacy pairing for any link carrying sensitive data or control, LESC's ECDH defeats the captured-pairing TK brute-force entirely [ryan2013woot]. Enforce a **minimum encryption key size of 16 bytes** and refuse a negotiated maximum below that, closing the BLE KNOB downgrade [antonioli2020knobble]. Keep the SoC's SMP/Security-Manager up to date and verify it against the SweynTooth class, in particular that it checks pairing state before honouring an encryption request, so a zero LTK can never be installed [garbelini2020sweyntooth]. - **Integrator.** Select SoCs/modules whose vendor has patched the SweynTooth Zero-LTK and related SMP flaws [cve-2019-19194], and disable Just-Works association on devices that have any input/output capability so authenticated pairing (passkey/OOB, with MITM protection) is used. Treat key size and pairing mode as procurement requirements, not defaults. - **Operator.** Pair sensitive devices once, in a controlled (low-RF-exposure) environment, since the offline crack needs the pairing exchange to have been captured; avoid repeated re-pairing in public. Where the platform allows, prefer devices that advertise LESC support and reject downgrades, and monitor for unexpected re-pairing prompts that could indicate a forced re-pair to harvest a fresh exchange. diff --git a/src/content/controls/rfsam-ble-ig-01.md b/src/content/controls/rfsam-ble-ig-01.md index 511e174..457fe01 100644 --- a/src/content/controls/rfsam-ble-ig-01.md +++ b/src/content/controls/rfsam-ble-ig-01.md @@ -10,7 +10,7 @@ applicability: deferred: true objective: >- Establish which Bluetooth controller (SoC) and host stack a target runs, and - whether either carries a known, named, CVE-tracked vulnerability — using the RF + whether either carries a known, named, CVE-tracked vulnerability, using the RF prerequisite (label/FCC-ID teardown and a passive advertising fingerprint) to feed the BSAM Information-Gathering controls. intro: >- @@ -28,7 +28,7 @@ prerequisites: - 'bettercap (BLE recon module) for device discovery and GATT enumeration' - 'catnip / Sniffle for advertising-channel capture; an FCC-ID / teardown lookup for the chipset' signal: - freq: '2.402–2.480 GHz (2.4 GHz ISM)' + freq: '2.402 to 2.480 GHz (2.4 GHz ISM)' bandwidth: '2 MHz per channel; 3 advertising channels (37/38/39) of 40 total' modulation: 'GFSK · PHYs: LE 1M (1 Mbps), LE 2M (BLE 5), LE Coded (BLE 5)' skill: beginner @@ -42,7 +42,7 @@ attacks: - cve-2019-19194 impact: >- Deadlocks, crashes, buffer overflows and a full LE Secure Connections - bypass (Zero-LTK) across BLE SoCs from multiple silicon vendors — + bypass (Zero-LTK) across BLE SoCs from multiple silicon vendors, decisive once the affected SoC is identified, before any RF capture. preconditions: >- Target runs an affected, unpatched BLE SoC (the disclosure names NXP, @@ -80,7 +80,7 @@ attacks: Target uses an affected TI CC2640/CC2650 (BLE-STACK v2.2.1 and related) controller, unpatched; attacker within advertising range. summary: >- - RCE in TI CC2640/CC2650 BLE chips — a controller-vulnerability case under + RCE in TI CC2640/CC2650 BLE chips, a controller-vulnerability case under BSAM-IG-02. - name: BleedingTooth cve: @@ -91,10 +91,10 @@ attacks: Adjacent, unauthenticated privilege escalation / potential code execution via improper L2CAP input validation in the Linux BlueZ host stack. preconditions: >- - Target host runs an affected Linux kernel/BlueZ (≈ 4.7.7–5.9.13); attacker + Target host runs an affected Linux kernel/BlueZ (≈ 4.7.7 to 5.9.13); attacker within Bluetooth range, no pairing required. summary: >- - Host-stack flaw in Linux BlueZ (L2CAP) — a host-stack-vulnerability case + Host-stack flaw in Linux BlueZ (L2CAP), a host-stack-vulnerability case under BSAM-IG-03. - name: BLESA refs: @@ -180,12 +180,12 @@ lastResearched: 2026-06-14 A large share of real-world BLE compromise is not a novel cryptographic break but an *unpatched* component with a known, named, CVE-tracked flaw. The flaw can live in either of two places, and identifying which is the whole point of this step: -- **The controller (the BLE SoC / radio firmware).** SweynTooth is the canonical example: a family of link-layer flaws across BLE SoCs from multiple silicon vendors — deadlocks, crashes, buffer overflows, and the Zero-LTK Installation, which forces an encryption setup with a zero-filled Long Term Key and thereby bypasses LE Secure Connections [garbelini2020sweyntooth]. The CISA ICS alert names the affected vendors (NXP, Cypress, Telink, Dialog, Microchip, STMicroelectronics, Texas Instruments) [cisa2020sweyntooth], and the Telink Zero-LTK instance is tracked as CVE-2019-19194 (CVSS 8.8) [cve-2019-19194]. BLEEDINGBIT is a second controller case: a remote code-execution buffer overflow reachable from a malformed advertising packet in TI CC2640/CC2650 BLE-STACK firmware (CVE-2018-16986, CVSS 8.8) [cve-2018-16986]. +- **The controller (the BLE SoC / radio firmware).** SweynTooth is the canonical example: a family of link-layer flaws across BLE SoCs from multiple silicon vendors, deadlocks, crashes, buffer overflows, and the Zero-LTK Installation, which forces an encryption setup with a zero-filled Long Term Key and thereby bypasses LE Secure Connections [garbelini2020sweyntooth]. The CISA ICS alert names the affected vendors (NXP, Cypress, Telink, Dialog, Microchip, STMicroelectronics, Texas Instruments) [cisa2020sweyntooth], and the Telink Zero-LTK instance is tracked as CVE-2019-19194 (CVSS 8.8) [cve-2019-19194]. BLEEDINGBIT is a second controller case: a remote code-execution buffer overflow reachable from a malformed advertising packet in TI CC2640/CC2650 BLE-STACK firmware (CVE-2018-16986, CVSS 8.8) [cve-2018-16986]. - **The host stack (the OS Bluetooth implementation).** BleedingTooth is the canonical example: improper L2CAP input validation in the Linux BlueZ stack lets an adjacent, unauthenticated attacker escalate privilege without pairing (CVE-2020-12351, CVSS 8.8) [cve-2020-12351]. BLESA sits at the host-stack/standard boundary: the BLE reconnection procedure does not mandate authentication, so several stacks (BlueZ, Android, iOS) let an attacker impersonate a previously-paired peer after forcing a reconnect [wu2020blesa]. A third category is **the standard itself**, independent of any one chip: KNOB downgrades BR/EDR encryption key entropy to as little as one byte during negotiation, making the session key brute-forceable (CVE-2019-9506, CVSS 8.1) [antonioli2019knob][cve-2019-9506]. -BSAM already provides mature, dedicated controls for exactly this triage: controller lifecycle status (BSAM-IG-01), controller vulnerabilities (BSAM-IG-02), host-stack vulnerabilities (BSAM-IG-03), and standard vulnerabilities (BSAM-IG-04). **RFSAM does not re-derive them.** This control exists to place the step in the RF assessment flow and to supply the one thing the RF assessor is best positioned to produce: the component inventory. That inventory comes from the label/FCC-ID and teardown for the silicon, and from a passive advertising fingerprint for the version and stack hints — the RF-capture prerequisite this control owns. The named-attack corpus above is **representative, not exhaustive** — it dates fast, so always check current vendor advisories and the Bluetooth SIG erratum feed against the components you actually identify. (For reference, the SweynTooth disclosure reports 11 new vulnerabilities under 13 CVE IDs; this control names only the canonical few rather than enumerating the family. BLESA is cited from its USENIX WOOT 2020 paper [wu2020blesa]; only the Apple instance carries a distinct CVE — CVE-2020-9770 — whose NVD entry does not name BLESA, so no CVE is asserted in this control's `attacks[].cve` for it.) +BSAM already provides mature, dedicated controls for exactly this triage: controller lifecycle status (BSAM-IG-01), controller vulnerabilities (BSAM-IG-02), host-stack vulnerabilities (BSAM-IG-03), and standard vulnerabilities (BSAM-IG-04). **RFSAM does not re-derive them.** This control exists to place the step in the RF assessment flow and to supply the one thing the RF assessor is best positioned to produce: the component inventory. That inventory comes from the label/FCC-ID and teardown for the silicon, and from a passive advertising fingerprint for the version and stack hints, the RF-capture prerequisite this control owns. The named-attack corpus above is **representative, not exhaustive**, it dates fast, so always check current vendor advisories and the Bluetooth SIG erratum feed against the components you actually identify. (For reference, the SweynTooth disclosure reports 11 new vulnerabilities under 13 CVE IDs; this control names only the canonical few rather than enumerating the family. BLESA is cited from its USENIX WOOT 2020 paper [wu2020blesa]; only the Apple instance carries a distinct CVE, CVE-2020-9770, whose NVD entry does not name BLESA, so no CVE is asserted in this control's `attacks[].cve` for it.) ## Procedure @@ -202,7 +202,7 @@ BSAM already provides mature, dedicated controls for exactly this triage: contro ```bash sudo bettercap -eval "ble.recon on; sleep 20; ble.show; q" ``` - Expected: a table of nearby devices with MAC, address type (public vs random/RPA), advertised name and vendor — the advertising fingerprint (RFSAM-RES-04). Note the address type: a fixed public address is trackable; a rotating Resolvable Private Address is not. + Expected: a table of nearby devices with MAC, address type (public vs random/RPA), advertised name and vendor, the advertising fingerprint (RFSAM-RES-04). Note the address type: a fixed public address is trackable; a rotating Resolvable Private Address is not. 3. **Capture raw advertising PDUs (optional, for manufacturer data).** Use a Sniffle-class sniffer via catnip to record the advertising channels into a PCAP for offline inspection in Wireshark. ```bash @@ -210,23 +210,23 @@ BSAM already provides mature, dedicated controls for exactly this triage: contro ``` Expected: an `adv.pcap` whose `BTLE` advertising frames carry the AdvData fields; the manufacturer-specific data's leading 2-byte Company Identifier resolves to the SoC/module vendor. -4. **Infer the BLE version and stack hints.** From the captured advertising — extended advertising and the 2M/Coded PHYs imply BLE 5.x; LE Legacy-only advertising implies an older controller. Combine with the host OS where known (a phone/gateway behind the device implies its stack — e.g. Android Fluoride, Linux BlueZ, Apple). - Expected: a (controller, host-stack, BLE version) tuple — the input the BSAM-IG controls need. +4. **Infer the BLE version and stack hints.** From the captured advertising, extended advertising and the 2M/Coded PHYs imply BLE 5.x; LE Legacy-only advertising implies an older controller. Combine with the host OS where known (a phone/gateway behind the device implies its stack, e.g. Android Fluoride, Linux BlueZ, Apple). + Expected: a (controller, host-stack, BLE version) tuple, the input the BSAM-IG controls need. 5. **Run the BSAM Information-Gathering controls against the identified components.** This is where the judgement is made; RFSAM hands off here. - - BSAM-IG-01 — controller lifecycle status (is the SoC end-of-life / unpatchable?). - - BSAM-IG-02 — controller vulnerabilities (e.g. SweynTooth, BLEEDINGBIT against the identified SoC). - - BSAM-IG-03 — host-stack vulnerabilities (e.g. BleedingTooth against the identified stack). - - BSAM-IG-04 — standard vulnerabilities (e.g. KNOB / spec-level reconnection issues). + - BSAM-IG-01, controller lifecycle status (is the SoC end-of-life / unpatchable?). + - BSAM-IG-02, controller vulnerabilities (e.g. SweynTooth, BLEEDINGBIT against the identified SoC). + - BSAM-IG-03, host-stack vulnerabilities (e.g. BleedingTooth against the identified stack). + - BSAM-IG-04, standard vulnerabilities (e.g. KNOB / spec-level reconnection issues). -6. **Carry the result forward as scoping input** to the RFSAM SP/PHY/LL capture controls. An end-of-life, unpatchable SoC with a published Zero-LTK bypass may make further dynamic RF testing moot — that finding is already decisive. +6. **Carry the result forward as scoping input** to the RFSAM SP/PHY/LL capture controls. An end-of-life, unpatchable SoC with a published Zero-LTK bypass may make further dynamic RF testing moot, that finding is already decisive. ## Field case A representative engagement against a connected door-lock module: - **Step 1 (label):** the FCC ID's internal photos showed a Telink TLSR8253 module. That part appears in the SweynTooth disclosure's affected list, immediately raising the Zero-LTK question (CVE-2019-19194) under BSAM-IG-02. -- **Step 2 (air):** `bettercap` saw the lock advertising under a `static random` address with manufacturer-specific data whose Company Identifier matched the module vendor — consistent with the label, and the device advertised LE-Legacy-only (no extended advertising), implying a pre-BLE-5 controller. +- **Step 2 (air):** `bettercap` saw the lock advertising under a `static random` address with manufacturer-specific data whose Company Identifier matched the module vendor, consistent with the label, and the device advertised LE-Legacy-only (no extended advertising), implying a pre-BLE-5 controller. - **Step 5 (BSAM):** running BSAM-IG-01/IG-02 against "Telink TLSR8253, firmware [FILL: SDK version read from the device / vendor]" is the decisive step. If the firmware predates the Telink fix, the device is exposed to the Zero-LTK Secure-Connections bypass regardless of how strong the pairing *looks*. The value RFSAM adds here is sequencing, not a new finding: the cheap, passive component inventory from this step scopes which SP/PHY/LL capture controls are worth running at all. @@ -237,6 +237,6 @@ The value RFSAM adds here is sequencing, not a new finding: the cheap, passive c **Developer (device firmware / SoC integration).** Track your BLE SoC vendor's advisory feed and the Bluetooth SIG erratum feed; ship the controller-firmware fixes for the named controller flaws (SweynTooth Zero-LTK / CVE-2019-19194 [cve-2019-19194], BLEEDINGBIT / CVE-2018-16986 [cve-2018-16986]). Enforce LE Secure Connections and reject a zero or out-of-order LTK install. Do not select an end-of-life SoC with no patch path for a new design. -**Integrator (host / OS stack).** Keep the host Bluetooth stack patched — BleedingTooth (CVE-2020-12351) is a BlueZ/kernel fix, so patch the kernel, not just the application [cve-2020-12351]. Enforce reconnection authentication so a forced reconnect cannot be impersonated (the BLESA class) [wu2020blesa]. Set and enforce a minimum encryption key size to defeat KNOB-style downgrade [antonioli2019knob][cve-2019-9506]. +**Integrator (host / OS stack).** Keep the host Bluetooth stack patched, BleedingTooth (CVE-2020-12351) is a BlueZ/kernel fix, so patch the kernel, not just the application [cve-2020-12351]. Enforce reconnection authentication so a forced reconnect cannot be impersonated (the BLESA class) [wu2020blesa]. Set and enforce a minimum encryption key size to defeat KNOB-style downgrade [antonioli2019knob][cve-2019-9506]. **Operator (deployment / fleet).** Maintain a component inventory (SoC + host stack + firmware version) per deployed device so a newly published CVE can be matched to the fleet quickly. Treat any controller that is end-of-life with no patch path as high-risk and plan replacement. Follow the remediation of the cited BSAM Information-Gathering controls (BSAM-IG-01…04), which own the formal judgement this control defers to. diff --git a/src/content/controls/rfsam-ble-ll-01.md b/src/content/controls/rfsam-ble-ll-01.md index ced2396..1ad50ce 100644 --- a/src/content/controls/rfsam-ble-ll-01.md +++ b/src/content/controls/rfsam-ble-ll-01.md @@ -14,20 +14,20 @@ objective: >- randomisation and enables passive tracking. intro: >- BLE advertising packets are transmitted in the clear and readable by any - passive observer — no connection or pairing required. Manufacturer-specific + passive observer, no connection or pairing required. Manufacturer-specific data, device names, and service UUIDs frequently leak product identity, user identity, or trackable identifiers, and a non-rotating identifier in the payload can re-link a device across address changes. The link-layer judgement of what counts as over-exposure is BSAM's (BSAM-DI-03 / DI-04 / DI-06); RFSAM - owns the RF-capture prerequisite — the passive advertising sweep that produces + owns the RF-capture prerequisite, the passive advertising sweep that produces the beacons to inspect. prerequisites: hardware: - - 'A CC1352-class BLE sniffer (CatSniffer / any Sniffle-capable board), an nRF52840 dongle (nRF Sniffer), or an Ubertooth One — anything that captures the three advertising channels and exports a PCAP.' + - 'A CC1352-class BLE sniffer (CatSniffer / any Sniffle-capable board), an nRF52840 dongle (nRF Sniffer), or an Ubertooth One, anything that captures the three advertising channels and exports a PCAP.' software: - 'Sniffle (or nRF Sniffer / Ubertooth), Wireshark for dissection, and optionally a host BLE stack (Bleak) for confirmatory enumeration.' signal: - freq: '2.402–2.480 GHz (2.4 GHz ISM); advertising on channels 37 (2.402), 38 (2.426), 39 (2.480 GHz)' + freq: '2.402 to 2.480 GHz (2.4 GHz ISM); advertising on channels 37 (2.402), 38 (2.426), 39 (2.480 GHz)' bandwidth: '2 MHz per channel' modulation: 'GFSK · LE 1M / 2M / Coded PHY' skill: beginner @@ -52,7 +52,7 @@ attacks: - givehchian2022physical impact: >- Tracking of a specific device by a per-radio hardware fingerprint, which no - amount of address or payload hygiene removes — an exposure to flag even + amount of address or payload hygiene removes, an exposure to flag even when the advertising content itself is clean. preconditions: >- Sustained capture of the device's transmissions with a capable receiver; @@ -117,11 +117,11 @@ lastResearched: 2026-06-14 --- ## Mechanism -BLE advertising is sent in the clear on three primary advertising channels — 37, 38 and 39 (2.402, 2.426 and 2.480 GHz) — and any passive receiver can read it without a connection or pairing [bt-core-spec]. The advertising payload (AdvData) is a sequence of length-tagged AD structures: the complete/shortened Local Name, advertised Service UUIDs, and Manufacturer Specific Data (AD type `0xFF`, which begins with a 16-bit Company Identifier) are the common identity-bearing fields, all defined in the Bluetooth Assigned Numbers [bt-assigned-numbers]. Device names routinely embed a product model or a user-chosen label; manufacturer data may embed serials, MACs, or rotating-but-linkable tokens. This control captures advertisements and inventories every field for sensitive or identity-bearing content — the judgement of what is *too much* is owned by BSAM (BSAM-DI-03 generic naming, BSAM-DI-04 sensitive-data exposure). +BLE advertising is sent in the clear on three primary advertising channels, 37, 38 and 39 (2.402, 2.426 and 2.480 GHz), and any passive receiver can read it without a connection or pairing [bt-core-spec]. The advertising payload (AdvData) is a sequence of length-tagged AD structures: the complete/shortened Local Name, advertised Service UUIDs, and Manufacturer Specific Data (AD type `0xFF`, which begins with a 16-bit Company Identifier) are the common identity-bearing fields, all defined in the Bluetooth Assigned Numbers [bt-assigned-numbers]. Device names routinely embed a product model or a user-chosen label; manufacturer data may embed serials, MACs, or rotating-but-linkable tokens. This control captures advertisements and inventories every field for sensitive or identity-bearing content, the judgement of what is *too much* is owned by BSAM (BSAM-DI-03 generic naming, BSAM-DI-04 sensitive-data exposure). -Address randomisation is the BLE privacy mechanism intended to stop this leaking into trackability: a device using privacy advertises with a Resolvable Private Address (RPA) generated from an Identity Resolving Key, rotating it on a timer whose recommended default `RPA_Timeout` is 900 s / 15 minutes (a configurable parameter, not a hard requirement) [bt-rpa-timeout]. Two well-documented attack families defeat it. **Address-carryover tracking** (Becker et al.) exploits the fact that the random address and the payload change on different schedules: an identifying token left unchanged in the payload re-links a freshly rotated address back to a known device, so randomisation alone does not prevent tracking [becker2019tracking]. The authors observed this against Windows 10, iOS and macOS devices and some wearables; Android devices that do not continuously advertise were not affected [becker2019tracking]. **Physical-layer fingerprint tracking** (Givehchian et al.) goes a level deeper, identifying a device from the per-radio hardware imperfections in its transmissions — independent of any over-the-air identifier — though the fingerprint can drift with temperature and collide between devices, which limits reliability in the field [givehchian2022physical]. Even a payload that is clean by BSAM's content rules can therefore still be trackable; flag the physical-layer exposure where the threat model warrants it. +Address randomisation is the BLE privacy mechanism intended to stop this leaking into trackability: a device using privacy advertises with a Resolvable Private Address (RPA) generated from an Identity Resolving Key, rotating it on a timer whose recommended default `RPA_Timeout` is 900 s / 15 minutes (a configurable parameter, not a hard requirement) [bt-rpa-timeout]. Two well-documented attack families defeat it. **Address-carryover tracking** (Becker et al.) exploits the fact that the random address and the payload change on different schedules: an identifying token left unchanged in the payload re-links a freshly rotated address back to a known device, so randomisation alone does not prevent tracking [becker2019tracking]. The authors observed this against Windows 10, iOS and macOS devices and some wearables; Android devices that do not continuously advertise were not affected [becker2019tracking]. **Physical-layer fingerprint tracking** (Givehchian et al.) goes a level deeper, identifying a device from the per-radio hardware imperfections in its transmissions, independent of any over-the-air identifier, though the fingerprint can drift with temperature and collide between devices, which limits reliability in the field [givehchian2022physical]. Even a payload that is clean by BSAM's content rules can therefore still be trackable; flag the physical-layer exposure where the threat model warrants it. -This control is **passive and observational** — capture and inventory only, no connection or transmission — so it carries no authorised-testing transmit step. It still requires authorisation to operate the radio in the target environment. +This control is **passive and observational**, capture and inventory only, no connection or transmission, so it carries no authorised-testing transmit step. It still requires authorisation to operate the radio in the target environment. ## Procedure @@ -145,12 +145,12 @@ Passive capture only. No connection is opened and nothing is transmitted; you ar ``` Expected: `ADV_IND` / `ADV_NONCONN_IND` / `ADV_SCAN_IND` frames. Inspect the dissected AD structures under *Bluetooth Low Energy Link Layer → Advertising Data*. -3. Inventory every AD structure for each advertiser — Local Name (`0x08`/`0x09`), Service UUIDs (`0x02`–`0x07`), and Manufacturer Specific Data (`0xFF`). Map the leading 16-bit Company Identifier in the `0xFF` data against the Bluetooth Assigned Numbers company list [bt-assigned-numbers]. +3. Inventory every AD structure for each advertiser, Local Name (`0x08`/`0x09`), Service UUIDs (`0x02` to `0x07`), and Manufacturer Specific Data (`0xFF`). Map the leading 16-bit Company Identifier in the `0xFF` data against the Bluetooth Assigned Numbers company list [bt-assigned-numbers]. 4. Classify the advertising address type and watch for stability: - **Public** or **Random Static** address → a fixed, directly trackable identifier (a BSAM-DI-06 finding). - **RPA** → check whether it actually rotates over the capture window. An RPA that never changes is equivalent to a static address. - - For any **rotating** RPA, scan the payloads for a token (serial, counter, name, or unique service-data blob) that *persists across* a rotation — that is the address-carryover linkage [becker2019tracking]. A simple way to surface candidates is to group frames by a stable payload field and see whether multiple distinct addresses share it: + - For any **rotating** RPA, scan the payloads for a token (serial, counter, name, or unique service-data blob) that *persists across* a rotation, that is the address-carryover linkage [becker2019tracking]. A simple way to surface candidates is to group frames by a stable payload field and see whether multiple distinct addresses share it: ```bash tshark -r ble_adv.pcap -Y "btle.advertising_header.pdu_type==0" \ -T fields -e btle.advertising_address -e btcommon.eir_ad.entry.company_id \ @@ -158,7 +158,7 @@ Passive capture only. No connection is opened and nothing is transmitted; you ar ``` Expected: if one payload value appears under two or more advertising addresses, randomisation is being defeated by a carried-over token. -5. Flag every human-meaningful name, embedded serial/MAC, and non-rotating identifier as a candidate exposure, and hand the over-exposure judgement to the BSAM controls (BSAM-DI-03 / DI-04 / DI-06). Optionally confirm a name field with a host scan — still passive, no pairing: +5. Flag every human-meaningful name, embedded serial/MAC, and non-rotating identifier as a candidate exposure, and hand the over-exposure judgement to the BSAM controls (BSAM-DI-03 / DI-04 / DI-06). Optionally confirm a name field with a host scan, still passive, no pairing: ```bash python3 -c "import asyncio;from bleak import BleakScanner;asyncio.run(BleakScanner.discover(timeout=10))" ``` @@ -166,15 +166,15 @@ Passive capture only. No connection is opened and nothing is transmitted; you ar ## Field case -Illustrative walkthrough — substitute the values you capture. In a passive sweep of an ordinary room, advertisers typically surface human-readable names that expose device class and ownership directly in the clear: a pet tracker advertising as `PwnPet_C81F`, an asset tracker as `TRKM_608015814_7795`, and several earbuds/wearables broadcasting model strings. No connection is made — the identity leak is in discovery alone. +Illustrative walkthrough, substitute the values you capture. In a passive sweep of an ordinary room, advertisers typically surface human-readable names that expose device class and ownership directly in the clear: a pet tracker advertising as `PwnPet_C81F`, an asset tracker as `TRKM_608015814_7795`, and several earbuds/wearables broadcasting model strings. No connection is made, the identity leak is in discovery alone. -The asset tracker is the instructive one for this control. Its advertised name `TRKM_608015814_7795` embeds what reads as a fixed serial/asset number; even if the device were to randomise its BLE address, that constant string in the Local Name AD structure re-links every rotation straight back to the same unit — the address-carryover linkage in concrete form [becker2019tracking]. Over a [FILL: capture-window length] window, record the tracker's advertising address as [FILL: address type — public / static / RPA, and whether it rotated], and confirm whether the `TRKM_…` name stays constant throughout: a constant Local Name spanning two or more distinct addresses is the carryover finding in the field. +The asset tracker is the instructive one for this control. Its advertised name `TRKM_608015814_7795` embeds what reads as a fixed serial/asset number; even if the device were to randomise its BLE address, that constant string in the Local Name AD structure re-links every rotation straight back to the same unit, the address-carryover linkage in concrete form [becker2019tracking]. Over a [FILL: capture-window length] window, record the tracker's advertising address as [FILL: address type, public / static / RPA, and whether it rotated], and confirm whether the `TRKM_…` name stays constant throughout: a constant Local Name spanning two or more distinct addresses is the carryover finding in the field. ## Remediation Layered, since the leak originates in product firmware but is inherited by integrators and seen by operators. -- **Developer (device firmware):** Use a generic, non-identifying Local Name — no model, serial, owner label, or hostname in advertising data (BSAM-DI-03). Keep model/serial and any sensitive attributes behind an authenticated, encrypted connection, never in AdvData (BSAM-DI-04). Advertise with a **Resolvable Private Address** and confirm it actually rotates (default 900 s; consider the randomized-RPA-update feature to break timing predictability) [bt-rpa-timeout], and put **no** stable token — serial, counter, or unique service-data blob — in the payload, or the RPA is defeated by carryover [becker2019tracking][bt-core-spec]. Be aware the physical-layer fingerprint is a residual exposure that content hygiene cannot close [givehchian2022physical]. +- **Developer (device firmware):** Use a generic, non-identifying Local Name, no model, serial, owner label, or hostname in advertising data (BSAM-DI-03). Keep model/serial and any sensitive attributes behind an authenticated, encrypted connection, never in AdvData (BSAM-DI-04). Advertise with a **Resolvable Private Address** and confirm it actually rotates (default 900 s; consider the randomized-RPA-update feature to break timing predictability) [bt-rpa-timeout], and put **no** stable token, serial, counter, or unique service-data blob, in the payload, or the RPA is defeated by carryover [becker2019tracking][bt-core-spec]. Be aware the physical-layer fingerprint is a residual exposure that content hygiene cannot close [givehchian2022physical]. - **Integrator:** During acceptance testing, run this passive sweep and reject builds that ship a public/static address, a never-rotating RPA, or identity-bearing AdvData. Verify any vendor "privacy mode" is enabled in the shipped configuration, not merely available (BSAM-DI-06). - **Operator:** Treat BLE advertising as broadcast-to-the-world. For trackable assets, minimise continuous advertising where the use case allows (intermittent advertising materially reduces carryover-tracking feasibility [becker2019tracking]), and account for the residual physical-layer-fingerprint risk in the threat model for high-sensitivity deployments [givehchian2022physical]. diff --git a/src/content/controls/rfsam-ble-ll-02.md b/src/content/controls/rfsam-ble-ll-02.md index 8d8831b..b9f5131 100644 --- a/src/content/controls/rfsam-ble-ll-02.md +++ b/src/content/controls/rfsam-ble-ll-02.md @@ -9,16 +9,16 @@ applicability: deferred: true objective: >- Determine whether the data-channel PDUs of a live BLE connection can be - followed and recorded off the air — recovering the hop sequence either from a + followed and recorded off the air, recovering the hop sequence either from a sniffed connection request or, for a connection already in progress, by - reconstructing it — producing a PCAP of link-layer traffic for inspection. + reconstructing it, producing a PCAP of link-layer traffic for inspection. intro: >- Once two BLE devices are connected, their traffic leaves the advertising channels and hops across the 37 data channels every connection event. RFSAM owns the RF-capture prerequisite: following that hop sequence and writing the data-channel PDUs to a PCAP. Whether the captured traffic constitutes a - finding — sensitive data in the clear, or a link that should have been - encrypted — is BSAM's judgement (BSAM-DI-04, BSAM-EN-02). Capture only your + finding, sensitive data in the clear, or a link that should have been + encrypted, is BSAM's judgement (BSAM-DI-04, BSAM-EN-02). Capture only your own devices or with explicit written authorisation. prerequisites: hardware: @@ -26,9 +26,9 @@ prerequisites: software: - 'Sniffle, the nRF Sniffer firmware, Ubertooth host tools, or ice9-bluetooth-sniffer; Wireshark to dissect the resulting PCAP' signal: - freq: '2.402–2.480 GHz (37 data channels, 2 MHz spacing; advertising on 37/38/39)' + freq: '2.402 to 2.480 GHz (37 data channels, 2 MHz spacing; advertising on 37/38/39)' bandwidth: '2 MHz per channel; ~80 MHz to see the whole band at once (bladeRF oversampling / SDR path)' - modulation: 'GFSK — LE 1M (1 Mbps), LE 2M and LE Coded (BLE 5)' + modulation: 'GFSK, LE 1M (1 Mbps), LE 2M and LE Coded (BLE 5)' skill: intermediate attacks: - name: Connection-following sniffing (CSA #1) @@ -73,7 +73,7 @@ attacks: summary: >- Reconstructs an already-running connection by listening across multiple channels and eliminating counter values incompatible with each observed - connection event — the basis of the SDR all-channel capture path. + connection event, the basis of the SDR all-channel capture path. references: - key: ryan2013btle title: 'Bluetooth: With Low Energy Comes Low Security' @@ -97,21 +97,21 @@ references: url: 'https://blog.lexfo.fr/sniffing-ble-sdr.html' type: blog - key: sniffle - title: 'Sniffle — a sniffer for Bluetooth 5 and 4.x LE' + title: 'Sniffle, a sniffer for Bluetooth 5 and 4.x LE' authors: Sultan Qasim Khan (NCC Group) venue: GitHub year: 2024 url: 'https://github.com/nccgroup/Sniffle' type: tool - key: btcorespec - title: 'Bluetooth Core Specification 5.4 — Vol 6 Part B, Link Layer (§2.3.3.1 CONNECT_IND PDU; §4.5.8 data channel selection)' + title: 'Bluetooth Core Specification 5.4, Vol 6 Part B, Link Layer (§2.3.3.1 CONNECT_IND PDU; §4.5.8 data channel selection)' authors: Bluetooth SIG venue: Bluetooth SIG year: 2023 url: 'https://www.bluetooth.com/wp-content/uploads/Files/Specification/HTML/Core-54/out/en/low-energy-controller/link-layer-specification.html' type: spec - key: btlejack - title: 'BtleJack — a new Bluetooth Low Energy swiss-army knife (README, "Sniffing for new connections")' + title: 'BtleJack, a new Bluetooth Low Energy swiss-army knife (README, "Sniffing for new connections")' authors: Damien Cauquil (virtualabs) venue: GitHub year: 2021 @@ -136,13 +136,13 @@ lastResearched: 2026-06-14 --- ## Mechanism -When a central accepts an advertiser, it sends a `CONNECT_IND` (`CONNECT_REQ`) PDU whose `LLData` field carries everything a third party needs to follow the connection: the 32-bit access address that will tag every subsequent data PDU, the CRC initialisation value, the channel map, the hop increment and the connection interval (Vol 6 Part B §2.3.3.1) [btcorespec]. From that moment the two devices leave the advertising channels (37/38/39) and exchange data PDUs on the 37 data channels, changing channel every connection event according to a channel selection algorithm (Vol 6 Part B §4.5.8) [btcorespec]. A sniffer that read the `CONNECT_IND` can compute the same channel sequence and hop along with the connection, recording every PDU — the technique Mike Ryan established for BLE [ryan2013btle]. +When a central accepts an advertiser, it sends a `CONNECT_IND` (`CONNECT_REQ`) PDU whose `LLData` field carries everything a third party needs to follow the connection: the 32-bit access address that will tag every subsequent data PDU, the CRC initialisation value, the channel map, the hop increment and the connection interval (Vol 6 Part B §2.3.3.1) [btcorespec]. From that moment the two devices leave the advertising channels (37/38/39) and exchange data PDUs on the 37 data channels, changing channel every connection event according to a channel selection algorithm (Vol 6 Part B §4.5.8) [btcorespec]. A sniffer that read the `CONNECT_IND` can compute the same channel sequence and hop along with the connection, recording every PDU, the technique Mike Ryan established for BLE [ryan2013btle]. -Two channel selection algorithms exist. Connections where at least one peer is pre-BLE-5, or where the `ChSel` bit is unset, use **CSA #1**, a simple `(channel + hopIncrement) mod 37` walk filtered by the channel map [btcorespec]. BLE 5 connections use **CSA #2**, a PRNG-style mapping that is harder to track; Cauquil reverse-engineered it and showed the hop sequence can be predicted from the access address alone, by measuring hops across a handful of channels [cauquil2019csa2]. Either way, following is a passive-observation problem, not a cryptographic one — the connection parameters are not secret. +Two channel selection algorithms exist. Connections where at least one peer is pre-BLE-5, or where the `ChSel` bit is unset, use **CSA #1**, a simple `(channel + hopIncrement) mod 37` walk filtered by the channel map [btcorespec]. BLE 5 connections use **CSA #2**, a PRNG-style mapping that is harder to track; Cauquil reverse-engineered it and showed the hop sequence can be predicted from the access address alone, by measuring hops across a handful of channels [cauquil2019csa2]. Either way, following is a passive-observation problem, not a cryptographic one, the connection parameters are not secret. -The harder case is a connection that is **already established** when the sniffer arrives: there is no `CONNECT_IND` left to read. The access address is still recoverable because it is in the header of every data PDU, but the channel map and the connection-event counter must be reconstructed. A wide-band radio watching several data channels at once can do this by elimination — each observed connection event rules out every counter value incompatible with it — until the hop sequence is pinned down [ballabriga2020sdr]. This is the basis of the SDR all-channel capture path (ice9), which is the only practical way to grab a long-lived connection you did not see start. +The harder case is a connection that is **already established** when the sniffer arrives: there is no `CONNECT_IND` left to read. The access address is still recoverable because it is in the header of every data PDU, but the channel map and the connection-event counter must be reconstructed. A wide-band radio watching several data channels at once can do this by elimination, each observed connection event rules out every counter value incompatible with it, until the hop sequence is pinned down [ballabriga2020sdr]. This is the basis of the SDR all-channel capture path (ice9), which is the only practical way to grab a long-lived connection you did not see start. -This is a **capture-feasibility** control. It produces a PCAP of link-layer traffic; it does not itself decide whether that traffic is a finding. If the connection is unencrypted, the captured data PDUs are readable in the clear, and the judgement of whether that exposes sensitive data, or whether encryption should have been mandatory, is BSAM's (BSAM-DI-04 sensitive-data exposure, BSAM-EN-02 force use of encryption). RFSAM owns only the RF prerequisite — reaching the point where those BSAM controls can be applied to real captured traffic. The same captured hop sequence is also the prerequisite that the active controls build on: decrypting a weakly-paired link (RFSAM-BLE-CR-01) and hijacking a live connection (RFSAM-BLE-AT-01) both start from following the connection that this control captures (RFSAM-RES-04). +This is a **capture-feasibility** control. It produces a PCAP of link-layer traffic; it does not itself decide whether that traffic is a finding. If the connection is unencrypted, the captured data PDUs are readable in the clear, and the judgement of whether that exposes sensitive data, or whether encryption should have been mandatory, is BSAM's (BSAM-DI-04 sensitive-data exposure, BSAM-EN-02 force use of encryption). RFSAM owns only the RF prerequisite, reaching the point where those BSAM controls can be applied to real captured traffic. The same captured hop sequence is also the prerequisite that the active controls build on: decrypting a weakly-paired link (RFSAM-BLE-CR-01) and hijacking a live connection (RFSAM-BLE-AT-01) both start from following the connection that this control captures (RFSAM-RES-04). ## Procedure @@ -158,7 +158,7 @@ All steps are passive reception. Capture only devices you own or are explicitly ```bash ./sniff_receiver.py -c 37 -m AA:BB:CC:DD:EE:FF -o conn.pcap ``` - Sniffle hops the advertising channels to catch the `CONNECT_IND`, reads the access address and hop parameters from it, and switches to following the data channels. Expected output: the `CONNECT_IND` line, then a stream of `Data / LL Data` PDUs with a stable access address — confirmation you are following the connection. The PCAP `conn.pcap` accumulates every captured PDU. (Add `-e -H` if the device connects via BT5 extended advertising; add `-l` for the Coded long-range PHY.) + Sniffle hops the advertising channels to catch the `CONNECT_IND`, reads the access address and hop parameters from it, and switches to following the data channels. Expected output: the `CONNECT_IND` line, then a stream of `Data / LL Data` PDUs with a stable access address, confirmation you are following the connection. The PCAP `conn.pcap` accumulates every captured PDU. (Add `-e -H` if the device connects via BT5 extended advertising; add `-l` for the Coded long-range PHY.) CatSniffer-native path (Electronic Cats): the catnip CLI runs the same Sniffle `conn_follow` mode on the CatSniffer and streams the followed connection into Wireshark over the Sniffle extcap: ```bash @@ -172,26 +172,26 @@ All steps are passive reception. Capture only devices you own or are explicitly ``` Filter on `btle.data_header` (data PDUs) and `btle.access_address == 0x........` (the connection's AA). A populated list means the data channel was followed. Apply `!btle.length == 0` to drop empty keep-alive PDUs and see only PDUs that carry payload. -4. **Classify the link as encrypted or clear.** In Wireshark, look for `LL_ENC_REQ` / `LL_ENC_RSP` and `LL_START_ENC_REQ` near the start of the connection. If they are absent, the link is unencrypted and the L2CAP/ATT payloads dissect directly — this is the input BSAM-DI-04 / BSAM-EN-02 judge. If they are present, the data PDUs after `LL_START_ENC_RSP` appear as encrypted blobs (decryption, where the pairing was weak, is RFSAM-BLE-CR-01's scope, not this control's). +4. **Classify the link as encrypted or clear.** In Wireshark, look for `LL_ENC_REQ` / `LL_ENC_RSP` and `LL_START_ENC_REQ` near the start of the connection. If they are absent, the link is unencrypted and the L2CAP/ATT payloads dissect directly, this is the input BSAM-DI-04 / BSAM-EN-02 judge. If they are present, the data PDUs after `LL_START_ENC_RSP` appear as encrypted blobs (decryption, where the pairing was weak, is RFSAM-BLE-CR-01's scope, not this control's). -5. **(Already-running connection, no `CONNECT_IND`.)** If the connection is already up when you start, the dedicated sniffer in steps 1–2 cannot lock on. Use the SDR all-channel path, which recovers the access address from data PDUs and reconstructs the hop sequence by elimination [ballabriga2020sdr]. `-l`/`--capture` captures live and `-w` writes the PCAP; `-a` sniffs all channels (requires a bladeRF 2.0), or use `-c`/`-C` to capture a slice of the band on a HackRF/USRP: +5. **(Already-running connection, no `CONNECT_IND`.)** If the connection is already up when you start, the dedicated sniffer in steps 1 to 2 cannot lock on. Use the SDR all-channel path, which recovers the access address from data PDUs and reconstructs the hop sequence by elimination [ballabriga2020sdr]. `-l`/`--capture` captures live and `-w` writes the PCAP; `-a` sniffs all channels (requires a bladeRF 2.0), or use `-c`/`-C` to capture a slice of the band on a HackRF/USRP: ```bash ice9-bluetooth -l -a -w established.pcap ``` - (HackRF slice instead of `-a`: `ice9-bluetooth -l -c 2440 -C 20 -w established.pcap`.) ice9 channelises the band, detects every BLE burst — including the PDUs of connections already in progress — and logs them to `established.pcap`; there is no separate "list addresses" step, so you filter the capture by the target's access address in Wireshark afterward (per step 3). Expected output: data PDUs accumulate in the PCAP and the connection's access address becomes visible once you filter on `btle.data_header`. This path needs CPU/GPU for channelisation and a wide-band radio (bladeRF for the full 80 MHz, HackRF for a slice). + (HackRF slice instead of `-a`: `ice9-bluetooth -l -c 2440 -C 20 -w established.pcap`.) ice9 channelises the band, detects every BLE burst, including the PDUs of connections already in progress, and logs them to `established.pcap`; there is no separate "list addresses" step, so you filter the capture by the target's access address in Wireshark afterward (per step 3). Expected output: data PDUs accumulate in the PCAP and the connection's access address becomes visible once you filter on `btle.data_header`. This path needs CPU/GPU for channelisation and a wide-band radio (bladeRF for the full 80 MHz, HackRF for a slice). ## Field case -A documented public example shows the full sequence end to end. The BtleJack README walks through catching a new connection off the air with `btlejack -c any`: it reports `Got CONNECT_REQ packet from 55:c5:95:6f:b4:df to 40:23:99:f6:0a:c0`, decodes the on-air `CONNECT_REQ` (`05 22 df b4 6f 95 c5 55 c0 0a f6 99 23 40 1d 7b 2f 0a 9a f4 93 01 12 00 27 00 00 00 d0 07 ff ff ff ff 1f 0b`), and prints the connection parameters straight from it — **access address `0x0a2f7b1d`**, CRC Init `0x93f49a`, hop interval 39 (a **48.75 ms** connection interval, since 39 × 1.25 ms), hop increment 11, channel map `0x1fffffffff` — then follows the link and emits the data-channel PDUs as `LL Data:` lines [btlejack]. That is exactly the observable this control produces: a stable access address tagging a continuous stream of followed data-channel PDUs, with the hop sequence read directly from the sniffed connection request. +A documented public example shows the full sequence end to end. The BtleJack README walks through catching a new connection off the air with `btlejack -c any`: it reports `Got CONNECT_REQ packet from 55:c5:95:6f:b4:df to 40:23:99:f6:0a:c0`, decodes the on-air `CONNECT_REQ` (`05 22 df b4 6f 95 c5 55 c0 0a f6 99 23 40 1d 7b 2f 0a 9a f4 93 01 12 00 27 00 00 00 d0 07 ff ff ff ff 1f 0b`), and prints the connection parameters straight from it, **access address `0x0a2f7b1d`**, CRC Init `0x93f49a`, hop interval 39 (a **48.75 ms** connection interval, since 39 × 1.25 ms), hop increment 11, channel map `0x1fffffffff`, then follows the link and emits the data-channel PDUs as `LL Data:` lines [btlejack]. That is exactly the observable this control produces: a stable access address tagging a continuous stream of followed data-channel PDUs, with the hop sequence read directly from the sniffed connection request. -The same workflow applies to your own bench device — a fitness band and its phone app on a test rig, not a third party's. With Sniffle on a CatSniffer parked on channel 37, the band advertises as a connectable peripheral; opening the app triggers the phone to connect, Sniffle logs the `CONNECT_IND`, latches the access address, and switches to following the data channels. Filtering `conn.pcap` in Wireshark on the connection's access address shows a continuous stream of data PDUs; if no `LL_ENC_REQ` appears, the link is unencrypted and the ATT notifications (e.g. step-count and heart-rate handles) dissect in the clear. +The same workflow applies to your own bench device, a fitness band and its phone app on a test rig, not a third party's. With Sniffle on a CatSniffer parked on channel 37, the band advertises as a connectable peripheral; opening the app triggers the phone to connect, Sniffle logs the `CONNECT_IND`, latches the access address, and switches to following the data channels. Filtering `conn.pcap` in Wireshark on the connection's access address shows a continuous stream of data PDUs; if no `LL_ENC_REQ` appears, the link is unencrypted and the ATT notifications (e.g. step-count and heart-rate handles) dissect in the clear. -That captured-in-the-clear traffic is exactly the input the BSAM judgement consumes: BSAM-DI-04 weighs whether those plaintext readings are sensitive-data exposure, and BSAM-EN-02 weighs whether the service should have refused to operate without encryption. RFSAM's part ends at producing the PCAP. The remaining per-device specifics on your own bench — the target model, the exact ATT handles exposed, and how many data PDUs were captured before the app disconnected — are left as placeholders rather than fabricated: [FILL: target device model, ATT handles seen, PDU count]. Do not assert a specific finding until these are captured on real hardware. +That captured-in-the-clear traffic is exactly the input the BSAM judgement consumes: BSAM-DI-04 weighs whether those plaintext readings are sensitive-data exposure, and BSAM-EN-02 weighs whether the service should have refused to operate without encryption. RFSAM's part ends at producing the PCAP. The remaining per-device specifics on your own bench, the target model, the exact ATT handles exposed, and how many data PDUs were captured before the app disconnected, are left as placeholders rather than fabricated: [FILL: target device model, ATT handles seen, PDU count]. Do not assert a specific finding until these are captured on real hardware. ## Remediation **Developer.** Capture-in-the-clear is only a problem because the link is readable. Require LE Secure Connections and refuse to expose any sensitive characteristic before encryption starts, so a follower's PCAP contains only encrypted blobs (the judgement BSAM-EN-02 makes) [btcorespec]. Do not place secrets in pre-encryption link-layer or unencrypted ATT traffic. -**Integrator.** Verify that the product as shipped actually negotiates encryption for the services that matter — run this capture against the integrated device and confirm `LL_ENC_REQ`/`LL_START_ENC_REQ` appear and that no readable sensitive payload precedes them. Prefer components that support and default to LE Secure Connections over LE Legacy pairing. +**Integrator.** Verify that the product as shipped actually negotiates encryption for the services that matter, run this capture against the integrated device and confirm `LL_ENC_REQ`/`LL_START_ENC_REQ` appear and that no readable sensitive payload precedes them. Prefer components that support and default to LE Secure Connections over LE Legacy pairing. -**Operator.** Treat the RF link as observable: anyone within range can record an unencrypted connection's data channel with sub-$150 hardware [ryan2013btle]. Where the threat model includes a nearby observer, deploy only devices whose sensitive functions are gated behind encryption, and re-test after firmware updates that touch the Bluetooth stack. Following a connection is a passive act — encryption is the only control that denies the captured bytes their meaning. +**Operator.** Treat the RF link as observable: anyone within range can record an unencrypted connection's data channel with sub-$150 hardware [ryan2013btle]. Where the threat model includes a nearby observer, deploy only devices whose sensitive functions are gated behind encryption, and re-test after firmware updates that touch the Bluetooth stack. Following a connection is a passive act, encryption is the only control that denies the captured bytes their meaning. diff --git a/src/content/controls/rfsam-ble-phy-01.md b/src/content/controls/rfsam-ble-phy-01.md index 7221aa0..0be4066 100644 --- a/src/content/controls/rfsam-ble-phy-01.md +++ b/src/content/controls/rfsam-ble-phy-01.md @@ -9,14 +9,14 @@ applicability: deferred: false objective: >- Verify that the toolchain can demodulate the BLE GFSK waveform and recover - clean link-layer bits — correlating the access address, de-whitening the PDU, - and validating the CRC — for the target's PHY (LE 1M / 2M / Coded), either on a + clean link-layer bits, correlating the access address, de-whitening the PDU, + and validating the CRC, for the target's PHY (LE 1M / 2M / Coded), either on a dedicated radio or by channelising a wideband SDR capture. intro: >- Everything above the air starts here: a BLE frame is GFSK, prefixed by a known preamble and a 32-bit access address, with its PDU and CRC whitened by a channel-seeded LFSR. This control checks that you can turn the RF into correct - bits — find the access address, de-whiten, and pass CRC — because every + bits, find the access address, de-whiten, and pass CRC, because every link-layer, crypto and attack control for BLE depends on clean per-channel bits. prerequisites: hardware: @@ -25,7 +25,7 @@ prerequisites: software: - 'Sniffle, nRF Sniffer, or Ubertooth host tools for the on-chip path; ice9-bluetooth-sniffer for the SDR path; Wireshark to read the decoded frames' signal: - freq: '2.402–2.480 GHz (40 × 2 MHz channels: 3 advertising 37/38/39 + 37 data)' + freq: '2.402 to 2.480 GHz (40 × 2 MHz channels: 3 advertising 37/38/39 + 37 data)' bandwidth: '2 MHz per channel (80 MHz full band)' modulation: 'GFSK (BT = 0.5, ~250 kHz deviation); PHYs LE 1M (1 Mbps), LE 2M, LE Coded' skill: intermediate @@ -35,7 +35,7 @@ attacks: - ryan2013woot impact: >- Lets a passive listener identify and follow an already-established, - unencrypted connection it never saw set up — the bit-recovery prerequisite + unencrypted connection it never saw set up, the bit-recovery prerequisite for downstream sniffing, decryption and injection. preconditions: >- Reception of data-channel packets from a live connection; no key needed @@ -43,7 +43,7 @@ attacks: summary: >- Treats any candidate 32 bits following a preamble-like pattern as a possible access address, then recovers CRCInit by running the over-the-air CRC back - through the reversible CRC LFSR — recovering the parameters needed to lock + through the reversible CRC LFSR, recovering the parameters needed to lock onto a connection from raw demodulated bits alone. - name: Link-layer fuzzing from recovered bits (SweynTooth) cve: @@ -56,7 +56,7 @@ attacks: SoCs, triggered by an in-range attacker. preconditions: >- An in-range central that can put crafted link-layer frames on the air to a - target peripheral — which presupposes exactly the demodulation / + target peripheral, which presupposes exactly the demodulation / bit-recovery capability this control verifies. summary: >- Set of 11 new vulnerabilities (13 CVE IDs) reported across BLE stacks from @@ -81,7 +81,7 @@ references: url: 'https://www.usenix.org/conference/atc20/presentation/garbelini' type: paper - key: btcorespec54 - title: 'Bluetooth Core Specification v5.4 — Vol 6 (Low Energy Controller), Part B: Link Layer Specification' + title: 'Bluetooth Core Specification v5.4, Vol 6 (Low Energy Controller), Part B: Link Layer Specification' authors: Bluetooth SIG venue: Bluetooth SIG year: 2023 @@ -95,7 +95,7 @@ references: url: 'https://www.bluetooth.com/bluetooth-le-primer/' type: spec - key: ice9repo - title: ice9-bluetooth-sniffer — Wireshark-compatible all-channel BLE sniffer (HackRF / bladeRF / USRP) + title: ice9-bluetooth-sniffer, Wireshark-compatible all-channel BLE sniffer (HackRF / bladeRF / USRP) authors: Mike Ryan (ICE9 Consulting) venue: GitHub year: 2023 @@ -120,8 +120,8 @@ lastResearched: 2026-06-14 A BLE link-layer packet is sent as a GFSK waveform: the Gaussian-filtered FSK keys the symbol with roughly ±250 kHz deviation and BT = 0.5 over a 1 µs symbol on the LE 1M PHY [[ryan2013woot]][[btcorespec54]]. Demodulation is therefore -an FM/frequency-discriminator step — the sign of the instantaneous frequency -offset is the bit — followed by clock recovery to slice symbols. Sniffers do +an FM/frequency-discriminator step, the sign of the instantaneous frequency +offset is the bit, followed by clock recovery to slice symbols. Sniffers do this on a dedicated radio's modem (the Ubertooth's CC2400 is configured to demodulate GFSK at the BLE deviation [[ryan2013woot]]); the SDR path instead channelises a wide capture, then FM-demodulates each 2 MHz channel in software @@ -132,7 +132,7 @@ with an 8-bit alternating preamble, then a 32-bit **access address** (AA), then the PDU and a 24-bit CRC [[ryan2013woot]][[btcorespec54]]. On the three advertising channels the AA is the fixed constant `0x8e89bed6`, so a demodulator finds packet boundaries by correlating against that known 32-bit value -[[ryan2013woot]][[ble-primer]]. The PDU and CRC are then **whitened** — XORed +[[ryan2013woot]][[ble-primer]]. The PDU and CRC are then **whitened**, XORed with the output of a 7-bit LFSR (taps at bits 4 and 7) whose seed is derived from the channel index alone, with no key involved; because the seed and LFSR are public, de-whitening "does not complicate sniffing" [[ryan2013woot]][[btcorespec54]]. @@ -143,7 +143,7 @@ For a connection the auditor never saw set up, the AA is a per-connection random value and not known in advance. Ryan's method treats any 32 bits following a preamble-like transition as a *candidate* AA, then recovers the connection's CRCInit by feeding the over-the-air CRC backwards through the CRC LFSR, which is -reversible — the same reversibility Spill and Bittau noted for classic Bluetooth +reversible, the same reversibility Spill and Bittau noted for classic Bluetooth holds for the BLE CRC [[ryan2013woot]]. This is what lets a passive listener lock onto and follow an already-established connection from raw bits, and it is the PHY-layer prerequisite for the connection-following described in RFSAM-RES-02. @@ -152,7 +152,7 @@ Why this control sits at PHY and matters on its own: bit recovery is the floor the rest of the stack stands on. Link-layer fuzzers such as SweynTooth drive a central that connects to the target peripheral and then sends malformed link-layer (and Security Manager) packets, or well-formed packets at the wrong -protocol state, mutating every field of the over-the-air frame — and putting +protocol state, mutating every field of the over-the-air frame, and putting crafted bits on the air presupposes exactly the demodulate/de-whiten/CRC capability verified here [[garbelini2020sweyntooth]]. RFSAM owns the spectrum and signal/PHY floors for BLE; the link-layer and @@ -172,7 +172,7 @@ where you have permission. only path that can grab an *already-established* connection (RFSAM-RES-01, RFSAM-RES-02, RFSAM-RES-03). -2. **On-chip path — capture and confirm bit recovery with Sniffle.** Scan the +2. **On-chip path, capture and confirm bit recovery with Sniffle.** Scan the advertising channels (passive, `-a` = don't follow connections) and write a PCAP for Wireshark: ```bash @@ -185,9 +185,9 @@ where you have permission. PHY/sync is wrong (wrong PHY selected, or signal too weak); add `-C` to also capture CRC-error packets when diagnosing this. -3. **On-chip path — verify on a non-advertising / data channel.** Drop the `-a` +3. **On-chip path, verify on a non-advertising / data channel.** Drop the `-a` flag so Sniffle follows the connection (following is its default) and confirm - it decodes data PDUs on channels other than 37/38/39 — this exercises the + it decodes data PDUs on channels other than 37/38/39, this exercises the per-channel whitening seed and the per-connection AA/CRCInit, not just the fixed advertising constants. Filter to the target advertiser's MAC to lock on: ```bash @@ -196,14 +196,14 @@ where you have permission. Expected: `LL Data` PDUs with `CRC ... [correct]` on data-channel indices. Read the connection's AA and CRCInit from the `CONNECT_IND` in Wireshark. -4. **SDR path — channelise and demodulate the whole band.** Capture / stream the +4. **SDR path, channelise and demodulate the whole band.** Capture / stream the band and let ice9 split it into 2 MHz channels, FM-demodulate each, and write an all-channel PCAP: ```bash ice9-bluetooth -l -i bladerf0 -a -w all_channels.pcap ``` Expected: per-channel BLE frames in `all_channels.pcap` openable in Wireshark. - The channelizer is the bottleneck — start narrow (e.g. 20 channels) and widen + The channelizer is the bottleneck, start narrow (e.g. 20 channels) and widen only while no overflow/dropped-sample is reported [[ice9repo]] (RFSAM-RES-03). Garbage / "random bytes" decoded instead of frames indicates the demod or sample rate is mismatched, per the tool's own troubleshooting note. @@ -216,13 +216,13 @@ where you have permission. ## Field case -Illustrative walkthrough — substitute the values you capture. Capturing a BLE +Illustrative walkthrough, substitute the values you capture. Capturing a BLE light controller's advertising on channel 37 with a CatSniffer running Sniffle, Wireshark dissects the `ADV_IND` with the fixed advertising access address -`0x8e89bed6` and `CRC ... [correct]` — confirming the demodulate → AA-correlate +`0x8e89bed6` and `CRC ... [correct]`, confirming the demodulate → AA-correlate → de-whiten → CRC chain on the radio's own modem. The useful detail is the de-whitening: the PDU bytes are only legible after the channel-37 whitening seed -is removed, and because that seed is derived from the channel index — not a key — +is removed, and because that seed is derived from the channel index, not a key, the same capture is readable by any sniffer, which is precisely why passive BLE sniffing is feasible at all [[ryan2013woot]]. @@ -230,14 +230,14 @@ On the SDR path, splitting the 80 MHz band into 40 × 2 MHz channels on a HackRF/bladeRF and FM-demodulating each is where the cost shows: ice9's channelizer is the stated bottleneck, so start the run at 20 channels and widen while watching for dropped samples. A naive full-band attempt on an underpowered -host decodes "a bunch of random bytes" rather than frames — the tool's own symptom -of a demod/rate mismatch [[ice9repo]]. The sensitivity margin — how many dB below -a clean capture the channelised SDR path still recovers frames — is bench-specific: +host decodes "a bunch of random bytes" rather than frames, the tool's own symptom +of a demod/rate mismatch [[ice9repo]]. The sensitivity margin, how many dB below +a clean capture the channelised SDR path still recovers frames, is bench-specific: [FILL: measured dB margin from a controlled bench capture]. ## Remediation -Bit recovery at PHY is an inherent, public property of the BLE waveform — the +Bit recovery at PHY is an inherent, public property of the BLE waveform, the GFSK parameters, the advertising access address, the whitening seeds and the CRC are all in the open specification, so there is no PHY-layer "fix" that hides the bits from a competent receiver [[ryan2013woot]][[btcorespec54]]. Remediation @@ -251,7 +251,7 @@ therefore lives above the recovered bits: [[garbelini2020sweyntooth]]. - **Integrator:** select SoCs/stacks with current firmware that patch the SweynTooth-class link-layer parsing bugs, and verify the device rejects - unencrypted access to anything sensitive — bit recovery on the air should never + unencrypted access to anything sensitive, bit recovery on the air should never translate into readable application data. - **Operator:** assume any in-range party can recover and read unencrypted BLE bits; for sensitive deployments, test in an RF-shielded environment and treat diff --git a/src/content/controls/rfsam-ble-sp-01.md b/src/content/controls/rfsam-ble-sp-01.md index f6f9886..dcbef86 100644 --- a/src/content/controls/rfsam-ble-sp-01.md +++ b/src/content/controls/rfsam-ble-sp-01.md @@ -9,14 +9,14 @@ applicability: deferred: false objective: >- Determine, before any analysis, which BLE advertising and data channels the - available receiver can observe at once — and therefore whether discovery, + available receiver can observe at once, and therefore whether discovery, full-band capture, or connection-following is reachable with the current hardware, or whether a 'not observed' is merely a visibility gap. intro: >- Before any analysis, establish whether the BLE channels of interest can actually be observed with the available hardware. BLE spreads across 40 channels over ~80 MHz of the 2.4 GHz band and a connection hops at every - connection event — wider and faster than most affordable SDRs can capture in a + connection event, wider and faster than most affordable SDRs can capture in a single pass, so the radio is a visibility trade-off that bounds every later control. prerequisites: @@ -25,7 +25,7 @@ prerequisites: software: - 'A spectrum viewer (Gqrx) to judge observable bandwidth; a BLE sniffer (Sniffle, ice9-bluetooth-sniffer, nRF Sniffer, or Ubertooth tools) to confirm what actually decodes' signal: - freq: '2.402–2.480 GHz (2.4 GHz ISM)' + freq: '2.402 to 2.480 GHz (2.4 GHz ISM)' bandwidth: '40 channels × 2 MHz spanning ~80 MHz; 2 MHz per channel' modulation: 'GFSK · PHYs: LE 1M (1 Mbps), LE 2M (BLE 5), LE Coded (BLE 5)' skill: beginner @@ -46,14 +46,14 @@ references: url: 'https://www.usenix.org/system/files/conference/woot13/woot13-ryan.pdf' type: paper - key: sniffle - title: Sniffle — a sniffer for Bluetooth 5 and 4.x LE + title: Sniffle, a sniffer for Bluetooth 5 and 4.x LE authors: NCC Group (S. Quinlan) venue: GitHub year: 2025 url: 'https://github.com/nccgroup/Sniffle' type: tool - key: ice9 - title: 'ice9-bluetooth-sniffer — Wireshark-compatible all-channel BLE sniffer for SDRs' + title: 'ice9-bluetooth-sniffer, Wireshark-compatible all-channel BLE sniffer for SDRs' authors: M. Ryan (ICE9 Consulting) venue: GitHub year: 2025 @@ -83,32 +83,32 @@ lastResearched: 2026-06-14 --- ## Mechanism -BLE occupies the 2.4 GHz ISM band, 2400–2483.5 MHz, divided into 40 channels of 2 MHz width [ble-primer]. Three of these are the primary advertising channels — 37, 38 and 39 — and the remaining 37 are general-purpose channels used for connection data [ble-primer]. The three advertising channels are deliberately spread across the band: channel 37 at 2402 MHz, channel 38 at 2426 MHz, and channel 39 at 2480 MHz, so an advertiser is hard to miss but the three cannot be tuned under one narrow receiver window simultaneously. +BLE occupies the 2.4 GHz ISM band, 2400 to 2483.5 MHz, divided into 40 channels of 2 MHz width [ble-primer]. Three of these are the primary advertising channels, 37, 38 and 39, and the remaining 37 are general-purpose channels used for connection data [ble-primer]. The three advertising channels are deliberately spread across the band: channel 37 at 2402 MHz, channel 38 at 2426 MHz, and channel 39 at 2480 MHz, so an advertiser is hard to miss but the three cannot be tuned under one narrow receiver window simultaneously. The signal is **GFSK** [ble-primer]. Once a central and peripheral connect, the connection does not stay on one channel: at the start of each connection event the radio deterministically selects a data channel via a channel-selection algorithm, hopping across the 37 data channels [ble-primer]. The practical consequence for an observer is that a single narrow window sees only the fraction of traffic that happens to land in it. -Following a live connection therefore means either (a) capturing the whole ~80 MHz at once and channelising it in software, or (b) recovering the hop parameters and retuning per hop. Mike Ryan's WOOT 2013 work is the canonical demonstration that a passive sniffer can recover the hop increment, channel map and access address from the connection request and then follow the hopping connection on commodity hardware [ryan2013ble]. That capability — and its prerequisite, *seeing enough of the band* — is what this control records. +Following a live connection therefore means either (a) capturing the whole ~80 MHz at once and channelising it in software, or (b) recovering the hop parameters and retuning per hop. Mike Ryan's WOOT 2013 work is the canonical demonstration that a passive sniffer can recover the hop increment, channel map and access address from the connection request and then follow the hopping connection on commodity hardware [ryan2013ble]. That capability, and its prerequisite, *seeing enough of the band*, is what this control records. The receiver bounds what is reachable: -- A **HackRF One** (~20 MHz instantaneous bandwidth) sees roughly a quarter of the band — one advertising channel at a time. Enough to camp channel 37 for discovery; not enough to watch all three advertising channels or follow a hopping connection by raw capture alone. -- A **bladeRF 2.0 micro** reaches ~56 MHz normally, and since the 2023.02 release an oversampling mode reaches 122.88 MHz instantaneous bandwidth (8-bit depth), enough to cover the whole 2.4 GHz BLE band in a single pass — the Nuand waterfall demonstration shows FHSS Bluetooth activity across the band at once [nuand122]. -- The SDR all-channel path is realised by **ice9-bluetooth-sniffer**, which channelises a wide I/Q stream from a HackRF / bladeRF / USRP into per-channel BLE decoders and can grab connections that are *already established* [ice9] — the case where you missed the connection request and so cannot replay Ryan's parameter-recovery [ryan2013ble]. +- A **HackRF One** (~20 MHz instantaneous bandwidth) sees roughly a quarter of the band, one advertising channel at a time. Enough to camp channel 37 for discovery; not enough to watch all three advertising channels or follow a hopping connection by raw capture alone. +- A **bladeRF 2.0 micro** reaches ~56 MHz normally, and since the 2023.02 release an oversampling mode reaches 122.88 MHz instantaneous bandwidth (8-bit depth), enough to cover the whole 2.4 GHz BLE band in a single pass, the Nuand waterfall demonstration shows FHSS Bluetooth activity across the band at once [nuand122]. +- The SDR all-channel path is realised by **ice9-bluetooth-sniffer**, which channelises a wide I/Q stream from a HackRF / bladeRF / USRP into per-channel BLE decoders and can grab connections that are *already established* [ice9], the case where you missed the connection request and so cannot replay Ryan's parameter-recovery [ryan2013ble]. - Dedicated sniffers sidestep the bandwidth question by hopping in firmware: **Sniffle** (CC1352/CatSniffer) follows connections across all BT5 PHYs and exports a PCAP [sniffle]. -This is a **capture-feasibility / spectrum** check, not a device finding — hence `criticality: info`. It establishes the auditor-capability baseline so later controls are interpreted correctly. +This is a **capture-feasibility / spectrum** check, not a device finding, hence `criticality: info`. It establishes the auditor-capability baseline so later controls are interpreted correctly. ## Procedure -> All steps below are passive reception only — no transmission. Even so, only observe RF you are authorised to capture; receiving BLE traffic from third-party devices may be regulated in your jurisdiction. +> All steps below are passive reception only, no transmission. Even so, only observe RF you are authorised to capture; receiving BLE traffic from third-party devices may be regulated in your jurisdiction. 1. **Establish the receiver's usable instantaneous bandwidth.** For an SDR, open a live spectrum view centred on the BLE band and read how wide a slice is visible: ```bash gqrx ``` - In Gqrx set the device to your radio, tune to **2440 MHz** (band centre) and set the input rate to the radio's maximum (HackRF: 20 Msps → ~20 MHz visible; bladeRF oversampled: up to ~122 Msps). Expected: the waterfall shows a band slice whose width equals the sample rate. On a HackRF you will see ~20 MHz — you cannot place 2402, 2426 and 2480 MHz in one window (they span 78 MHz). Record the visible width. + In Gqrx set the device to your radio, tune to **2440 MHz** (band centre) and set the input rate to the radio's maximum (HackRF: 20 Msps → ~20 MHz visible; bladeRF oversampled: up to ~122 Msps). Expected: the waterfall shows a band slice whose width equals the sample rate. On a HackRF you will see ~20 MHz, you cannot place 2402, 2426 and 2480 MHz in one window (they span 78 MHz). Record the visible width. -2. **Confirm whether the full band fits in one pass.** The three advertising channels span 2402–2480 MHz = 78 MHz, and the data channels fill the gaps, so simultaneous capture needs ≥ ~80 MHz of instantaneous bandwidth. +2. **Confirm whether the full band fits in one pass.** The three advertising channels span 2402 to 2480 MHz = 78 MHz, and the data channels fill the gaps, so simultaneous capture needs ≥ ~80 MHz of instantaneous bandwidth. ```bash # bladeRF oversampling mode: sample the whole band at once bladeRF-cli -e "set samplerate 122000000; set frequency rx 2441000000" @@ -116,7 +116,7 @@ This is a **capture-feasibility / spectrum** check, not a device finding — hen Expected: a bladeRF in oversampling mode accepts the rate and covers the band [nuand122]; a HackRF cannot (rate exceeds its IBW) and must tune to one channel at a time. 3. **If full-band capture is not possible, decide the strategy** (record which applies): - - **Camp one channel** for discovery — tune the radio to 2402 MHz and rely on a sniffer to catch advertisements that land on channel 37. + - **Camp one channel** for discovery, tune the radio to 2402 MHz and rely on a sniffer to catch advertisements that land on channel 37. - **Channelise the whole band** with the SDR all-channel path (RFSAM-RES-03): ```bash ice9-bluetooth-sniffer -l # list detected SDRs and capabilities @@ -133,9 +133,9 @@ This is a **capture-feasibility / spectrum** check, not a device finding — hen ## Field case -Auditing a generic BLE LED controller with a **HackRF One** in Gqrx, tuned to 2440 MHz at 20 Msps: the waterfall showed ~20 MHz of spectrum — about a quarter of the BLE band. Advertising channel 37 (2402 MHz) sat well outside that window, so to see the controller's advertisements the radio had to be retuned to 2402 MHz; once camped there, the periodic advertising bursts were visible and discovery (the IG/LL handoff) was feasible. Following the live connection by raw HackRF capture was **not** feasible — the connection hops across the 37 data channels that a 20 MHz window cannot hold at once — so connection work required either a firmware-hopping sniffer (Sniffle on a CatSniffer) or the ice9 channelisation path. +Auditing a generic BLE LED controller with a **HackRF One** in Gqrx, tuned to 2440 MHz at 20 Msps: the waterfall showed ~20 MHz of spectrum, about a quarter of the BLE band. Advertising channel 37 (2402 MHz) sat well outside that window, so to see the controller's advertisements the radio had to be retuned to 2402 MHz; once camped there, the periodic advertising bursts were visible and discovery (the IG/LL handoff) was feasible. Following the live connection by raw HackRF capture was **not** feasible, the connection hops across the 37 data channels that a 20 MHz window cannot hold at once, so connection work required either a firmware-hopping sniffer (Sniffle on a CatSniffer) or the ice9 channelisation path. -Switching to a **bladeRF 2.0 micro** in oversampling mode (122.88 MHz [nuand122]) and feeding ice9-bluetooth-sniffer, the whole band was captured in one pass and an already-established connection could be picked up without ever seeing its `CONNECT_IND` [ice9] — the case Ryan's parameter-recovery cannot reach because there is no connection request to read [ryan2013ble]. +Switching to a **bladeRF 2.0 micro** in oversampling mode (122.88 MHz [nuand122]) and feeding ice9-bluetooth-sniffer, the whole band was captured in one pass and an already-established connection could be picked up without ever seeing its `CONNECT_IND` [ice9], the case Ryan's parameter-recovery cannot reach because there is no connection request to read [ryan2013ble]. Recorded capture-feasibility baseline for this engagement: @@ -150,6 +150,6 @@ This field case is a representative worked example, not a single measured engage This control is an **auditor-capability baseline**, not a device weakness, so the primary output is documentation, not a fix. Layered guidance: -- **Auditor / operator** — Record the capture envelope (radio, visible bandwidth, channels observable simultaneously, connection-following method) at the top of every BLE assessment. Interpret every later 'not observed' against it: under a 20 MHz window, absence of a signal is a visibility gap, never proof the device is silent. Where the budget radio cannot follow connections, escalate to a full-band SDR (bladeRF oversampling [nuand122]) or a firmware-hopping sniffer (Sniffle [sniffle]) before concluding. -- **Integrator** — Provision the kit to the threat being tested: discovery only needs a single-channel camp, but any connection-following, injection, or established-connection capture needs either ≥ ~80 MHz instantaneous bandwidth or a firmware sniffer with connection-following (and, for already-established connections, the ice9 SDR path [ice9]). Do not infer link security from a capture gap. -- **Developer** — For a device under test, predictable, fixed advertising and low-entropy connection parameters make a connection trivially followable on commodity hardware [ryan2013ble]; using a Resolvable Private Address and standard hopping does not stop capture (this is a spectrum property, not a control), but it raises the effort and is assessed at the link/crypto layers, not here. +- **Auditor / operator**, Record the capture envelope (radio, visible bandwidth, channels observable simultaneously, connection-following method) at the top of every BLE assessment. Interpret every later 'not observed' against it: under a 20 MHz window, absence of a signal is a visibility gap, never proof the device is silent. Where the budget radio cannot follow connections, escalate to a full-band SDR (bladeRF oversampling [nuand122]) or a firmware-hopping sniffer (Sniffle [sniffle]) before concluding. +- **Integrator**, Provision the kit to the threat being tested: discovery only needs a single-channel camp, but any connection-following, injection, or established-connection capture needs either ≥ ~80 MHz instantaneous bandwidth or a firmware sniffer with connection-following (and, for already-established connections, the ice9 SDR path [ice9]). Do not infer link security from a capture gap. +- **Developer**, For a device under test, predictable, fixed advertising and low-entropy connection parameters make a connection trivially followable on commodity hardware [ryan2013ble]; using a Resolvable Private Address and standard hopping does not stop capture (this is a spectrum property, not a control), but it raises the effort and is assessed at the link/crypto layers, not here. diff --git a/src/content/controls/rfsam-btc-ap-01.md b/src/content/controls/rfsam-btc-ap-01.md index 2f915c1..7e5525a 100644 --- a/src/content/controls/rfsam-btc-ap-01.md +++ b/src/content/controls/rfsam-btc-ap-01.md @@ -10,14 +10,14 @@ applicability: deferred: true objective: >- Determine which services and profiles a Bluetooth Classic (BR/EDR) device - exposes above the link — the SDP service directory, RFCOMM serial/AT-command - channels, HID, A2DP/HFP audio and OBEX object exchange — and verify what the + exposes above the link, the SDP service directory, RFCOMM serial/AT-command + channels, HID, A2DP/HFP audio and OBEX object exchange, and verify what the device trusts on those profiles without (or before) authentication. intro: >- Above the BR/EDR link sits the application surface: the profiles a device publishes in its SDP directory and the channels behind them. RFSAM owns the - RF prerequisite — reaching the device's host stack over the air with a standard - adapter — and drives enumeration from a Linux BlueZ host, while the + RF prerequisite, reaching the device's host stack over the air with a standard + adapter, and drives enumeration from a Linux BlueZ host, while the service-access-control finding (which profiles must demand authentication) is assessed under BSAM (BSAM-SE-03). BlueBorne is the canonical reminder that this layer is reachable: it is a host-stack attack family that lands over the same @@ -28,7 +28,7 @@ prerequisites: software: - 'Linux with the BlueZ stack: bluetoothctl, sdptool, l2ping, plus profile tools such as obexftp and the hcitool/btmgmt utilities' signal: - freq: '2.402–2.480 GHz (79 RF channels × 1 MHz, adaptive frequency hopping ~1600 hops/s)' + freq: '2.402 to 2.480 GHz (79 RF channels × 1 MHz, adaptive frequency hopping ~1600 hops/s)' bandwidth: '1 MHz per RF channel' modulation: 'GFSK 1 Mbps (Basic Rate); π/4-DQPSK 2 Mbps & 8DPSK 3 Mbps (EDR)' skill: intermediate @@ -39,11 +39,11 @@ attacks: refs: - armis2017blueborne - cve-2017-1000250 - impact: Remote attacker reads sensitive bytes out of the bluetoothd process memory via crafted SDP search-attribute requests — no pairing required. + impact: Remote attacker reads sensitive bytes out of the bluetoothd process memory via crafted SDP search-attribute requests, no pairing required. preconditions: A reachable BR/EDR host running a vulnerable BlueZ SDP server (5.46 and earlier); the device need not be discoverable, only addressable. summary: >- Out-of-bounds read in the BlueZ SDP server reached over the same service - directory this control enumerates — the SDP surface is itself attack + directory this control enumerates, the SDP surface is itself attack surface, not just a map of it. - name: 'BlueBorne (Linux L2CAP kernel RCE)' cve: @@ -51,8 +51,8 @@ attacks: refs: - armis2017blueborne - cve-2017-1000251 - impact: Remote code execution in Linux kernel space via a stack overflow in L2CAP configuration-response handling — full host compromise over the air. - preconditions: A reachable Linux BR/EDR host on kernel 2.6.32–4.13.1; no pairing or discoverable mode needed. + impact: Remote code execution in Linux kernel space via a stack overflow in L2CAP configuration-response handling, full host compromise over the air. + preconditions: A reachable Linux BR/EDR host on kernel 2.6.32 to 4.13.1; no pairing or discoverable mode needed. summary: >- The canonical above-the-link Bluetooth Classic takeover: a host-stack overflow reached over L2CAP, the transport every profile in this control @@ -66,11 +66,11 @@ attacks: - armis2017blueborne-poc - cve-2017-0781 - cve-2017-0785 - impact: Remote code execution and information disclosure in the Android Bluetooth stack reachable over the air on Android 4.4.4–8.0. + impact: Remote code execution and information disclosure in the Android Bluetooth stack reachable over the air on Android 4.4.4 to 8.0. preconditions: A reachable, unpatched Android BR/EDR host; no pairing or discoverable mode needed. summary: >- - The Android arm of BlueBorne — the same host-stack-over-profiles class on a - different OS — with Armis-published proof-of-concept exploit code. + The Android arm of BlueBorne, the same host-stack-over-profiles class on a + different OS, with Armis-published proof-of-concept exploit code. references: - key: armis2017blueborne title: 'BlueBorne Technical White Paper' @@ -80,7 +80,7 @@ references: url: 'https://info.armis.com/rs/645-PDC-047/images/BlueBorne%20Technical%20White%20Paper_20171130.pdf' type: paper - key: armis2017blueborne-poc - title: 'BlueBorne — PoC scripts demonstrating the BlueBorne vulnerabilities' + title: 'BlueBorne, PoC scripts demonstrating the BlueBorne vulnerabilities' authors: Armis Security venue: GitHub year: 2017 @@ -111,7 +111,7 @@ references: url: 'https://nvd.nist.gov/vuln/detail/CVE-2017-0785' type: cve - key: bluez-project - title: 'BlueZ — the official Linux Bluetooth protocol stack (sdptool, l2ping, bluetoothctl)' + title: 'BlueZ, the official Linux Bluetooth protocol stack (sdptool, l2ping, bluetoothctl)' authors: BlueZ project venue: GitHub year: 2026 @@ -129,13 +129,13 @@ lastResearched: 2026-06-14 --- ## Mechanism -Bluetooth Classic exposes its application surface through profiles, and every profile is advertised in the Service Discovery Protocol (SDP) directory. Querying SDP returns the device's service records — each naming a profile (Serial Port / RFCOMM, HID, A2DP, HFP/HSP, OBEX Object Push, PBAP, and so on) and the L2CAP PSM or RFCOMM channel behind it. SDP is therefore the map of what the device trusts above the link, and enumerating it is the first move at this layer. The standard driver is a Linux host's BlueZ stack over a commodity USB adapter — the same host workflow BSAM's Bluetooth controls assume — so RFSAM owns only the RF prerequisite (reaching the device's host stack over the air) and defers the service-access-control judgement (which of those profiles may be reached without authentication) to BSAM-SE-03 (bluez-project). +Bluetooth Classic exposes its application surface through profiles, and every profile is advertised in the Service Discovery Protocol (SDP) directory. Querying SDP returns the device's service records, each naming a profile (Serial Port / RFCOMM, HID, A2DP, HFP/HSP, OBEX Object Push, PBAP, and so on) and the L2CAP PSM or RFCOMM channel behind it. SDP is therefore the map of what the device trusts above the link, and enumerating it is the first move at this layer. The standard driver is a Linux host's BlueZ stack over a commodity USB adapter, the same host workflow BSAM's Bluetooth controls assume, so RFSAM owns only the RF prerequisite (reaching the device's host stack over the air) and defers the service-access-control judgement (which of those profiles may be reached without authentication) to BSAM-SE-03 (bluez-project). -The reason this layer matters is that the SDP directory is not merely descriptive — it is reachable, and so is everything behind it. **BlueBorne** is the canonical demonstration: a family of host-stack vulnerabilities reached over Bluetooth without pairing and without the target being discoverable (armis2017blueborne). On Linux the SDP server itself leaks `bluetoothd` process memory through crafted search-attribute requests (CVE-2017-1000250), and the kernel L2CAP layer that every profile rides on can be driven to remote code execution (CVE-2017-1000251) (cve-2017-1000250, cve-2017-1000251). The Android arm of the same family adds RCE (CVE-2017-0781) and an information leak in the Android Bluetooth SDP server (CVE-2017-0785), with proof-of-concept code published by Armis (armis2017blueborne-poc, cve-2017-0781, cve-2017-0785). The SDP framing of CVE-2017-0785 is Armis's own: NVD records it simply as an Android Bluetooth information-disclosure issue, while the Armis PoC `android/` exploit uses it explicitly as "the SDP Information leak vulnerability (CVE-2017-0785) to bypass ASLR" ahead of the CVE-2017-0781 RCE (armis2017blueborne-poc). Treat this CVE set as representative of the above-the-link/host-stack class, not as a current advisory list — check vendor advisories for the target's controller SoC and host OS before testing. +The reason this layer matters is that the SDP directory is not merely descriptive, it is reachable, and so is everything behind it. **BlueBorne** is the canonical demonstration: a family of host-stack vulnerabilities reached over Bluetooth without pairing and without the target being discoverable (armis2017blueborne). On Linux the SDP server itself leaks `bluetoothd` process memory through crafted search-attribute requests (CVE-2017-1000250), and the kernel L2CAP layer that every profile rides on can be driven to remote code execution (CVE-2017-1000251) (cve-2017-1000250, cve-2017-1000251). The Android arm of the same family adds RCE (CVE-2017-0781) and an information leak in the Android Bluetooth SDP server (CVE-2017-0785), with proof-of-concept code published by Armis (armis2017blueborne-poc, cve-2017-0781, cve-2017-0785). The SDP framing of CVE-2017-0785 is Armis's own: NVD records it simply as an Android Bluetooth information-disclosure issue, while the Armis PoC `android/` exploit uses it explicitly as "the SDP Information leak vulnerability (CVE-2017-0785) to bypass ASLR" ahead of the CVE-2017-0781 RCE (armis2017blueborne-poc). Treat this CVE set as representative of the above-the-link/host-stack class, not as a current advisory list, check vendor advisories for the target's controller SoC and host OS before testing. ## Procedure -> Authorised testing only — enumerate and exercise profiles solely on devices you own or are explicitly contracted to assess. SDP browsing is passive, but pairing, RFCOMM connection and OBEX transfer are active interactions with the target's host stack. +> Authorised testing only, enumerate and exercise profiles solely on devices you own or are explicitly contracted to assess. SDP browsing is passive, but pairing, RFCOMM connection and OBEX transfer are active interactions with the target's host stack. 1. Bring up the local adapter and confirm it is a BR/EDR controller: ```bash @@ -144,7 +144,7 @@ The reason this layer matters is that the SDP directory is not merely descriptiv ``` You want a controller that reports BR/EDR (not an LE-only dongle). -2. Discover the target and record its BD_ADDR and Class of Device (the IG/SP work feeds this — you may already have the address): +2. Discover the target and record its BD_ADDR and Class of Device (the IG/SP work feeds this, you may already have the address): ```bash bluetoothctl [bluetooth]# scan on @@ -156,9 +156,9 @@ The reason this layer matters is that the SDP directory is not merely descriptiv ```bash sudo l2ping -c 5 AA:BB:CC:DD:EE:FF ``` - Replies confirm the BR/EDR host is up and answering — the prerequisite for everything below. + Replies confirm the BR/EDR host is up and answering, the prerequisite for everything below. -4. Enumerate the SDP service directory — the core of this control: +4. Enumerate the SDP service directory, the core of this control: ```bash sdptool browse AA:BB:CC:DD:EE:FF ``` @@ -178,14 +178,14 @@ The reason this layer matters is that the SDP directory is not merely descriptiv ``` - **HID / audio (A2DP/HFP)**: note whether `bluetoothctl pair`/`connect` succeeds with no PIN or with a fixed/known PIN, and whether the profile activates without confirmation on the device. -6. Record, per profile: the channel/PSM, whether it required authentication, and what it did when reached without it. That table — which services answer unauthenticated — is the finding handed to **BSAM-SE-03** for the service-access-control judgement. +6. Record, per profile: the channel/PSM, whether it required authentication, and what it did when reached without it. That table, which services answer unauthenticated, is the finding handed to **BSAM-SE-03** for the service-access-control judgement. ## Field case -Illustrative walkthrough — substitute the values you capture. Against a generic Bluetooth hands-free car kit on the bench, the pattern looks like this: `sdptool browse` returns a Serial Port (RFCOMM) record on channel 1 and a Handsfree Gateway record, alongside the expected A2DP sink. `l2ping` answers immediately even though the unit is not in pairing mode, confirming the host stack is reachable from its BD_ADDR alone. Binding RFCOMM channel 1 with `rfcomm connect /dev/rfcomm0 1` and sending `AT` over `screen /dev/rfcomm0 115200` produces an `OK` — the serial channel answering AT commands before any pairing completed, which is exactly the unauthenticated-service condition BSAM-SE-03 exists to flag. A harmless car kit is the demonstrator; the same enumeration step against an OBD-II dongle or a point-of-sale terminal is where an exposed RFCOMM/AT or OBEX channel becomes consequential. Record the real values from your own engagement: [FILL: real device model, BD_ADDR OUI, exact sdptool record and channel]. +Illustrative walkthrough, substitute the values you capture. Against a generic Bluetooth hands-free car kit on the bench, the pattern looks like this: `sdptool browse` returns a Serial Port (RFCOMM) record on channel 1 and a Handsfree Gateway record, alongside the expected A2DP sink. `l2ping` answers immediately even though the unit is not in pairing mode, confirming the host stack is reachable from its BD_ADDR alone. Binding RFCOMM channel 1 with `rfcomm connect /dev/rfcomm0 1` and sending `AT` over `screen /dev/rfcomm0 115200` produces an `OK`, the serial channel answering AT commands before any pairing completed, which is exactly the unauthenticated-service condition BSAM-SE-03 exists to flag. A harmless car kit is the demonstrator; the same enumeration step against an OBD-II dongle or a point-of-sale terminal is where an exposed RFCOMM/AT or OBEX channel becomes consequential. Record the real values from your own engagement: [FILL: real device model, BD_ADDR OUI, exact sdptool record and channel]. ## Remediation -- **Developer (device firmware):** Publish only the profiles the product actually needs in SDP, and require authentication and authorisation on every channel that carries data or commands — never leave an RFCOMM/AT or OBEX channel reachable pre-pairing. Reject legacy PIN pairing and "Just Works" where the profile handles anything sensitive. Keep the controller SoC and host Bluetooth stack patched against the host-stack class (BlueBorne and its successors); treat the cited CVE set as representative and track current advisories for your specific stack (armis2017blueborne). +- **Developer (device firmware):** Publish only the profiles the product actually needs in SDP, and require authentication and authorisation on every channel that carries data or commands, never leave an RFCOMM/AT or OBEX channel reachable pre-pairing. Reject legacy PIN pairing and "Just Works" where the profile handles anything sensitive. Keep the controller SoC and host Bluetooth stack patched against the host-stack class (BlueBorne and its successors); treat the cited CVE set as representative and track current advisories for your specific stack (armis2017blueborne). - **Integrator:** Choose modules and host stacks with maintained security updates; verify, by running the enumeration above on the assembled product, that no profile answers unauthenticated. Disable unused profiles at integration time rather than trusting defaults. -- **Operator:** Keep the device non-discoverable when not actively pairing, apply firmware updates promptly, and unpair stale bondings. Recognise that non-discoverable is not unreachable — a known BD_ADDR still reaches the host stack — so patching the stack, not hiding it, is the durable control. The which-services-must-be-locked judgement is owned by BSAM-SE-03. +- **Operator:** Keep the device non-discoverable when not actively pairing, apply firmware updates promptly, and unpair stale bondings. Recognise that non-discoverable is not unreachable, a known BD_ADDR still reaches the host stack, so patching the stack, not hiding it, is the durable control. The which-services-must-be-locked judgement is owned by BSAM-SE-03. diff --git a/src/content/controls/rfsam-btc-at-01.md b/src/content/controls/rfsam-btc-at-01.md index 9b16627..90f9937 100644 --- a/src/content/controls/rfsam-btc-at-01.md +++ b/src/content/controls/rfsam-btc-at-01.md @@ -9,12 +9,12 @@ applicability: deferred: false objective: >- Determine how a Bluetooth Classic (BR/EDR) controller withstands malformed - baseband/LMP traffic and wholesale 2.4 GHz RF denial — does it crash, deadlock, - reboot, run attacker code, or merely degrade — and whether the link survives or + baseband/LMP traffic and wholesale 2.4 GHz RF denial, does it crash, deadlock, + reboot, run attacker code, or merely degrade, and whether the link survives or silently downgrades under stress. intro: >- Going active against Bluetooth Classic means transmitting in the 2.4 GHz ISM - band and poking a live BR/EDR controller — authorised testing only, on devices + band and poking a live BR/EDR controller, authorised testing only, on devices you own or are contracted to assess. The accessible reference capability is BrakTooth: a baseband/LMP exploit suite that crashes, deadlocks, or on some chips runs code, firing from a $5 ESP32. A broadband jammer adds the @@ -22,12 +22,12 @@ intro: >- follow-ons. prerequisites: hardware: - - 'An original ESP32 (BR/EDR-capable) dev board flashed with the BrakTooth firmware — the patched ESP-BT controller is the attack radio' + - 'An original ESP32 (BR/EDR-capable) dev board flashed with the BrakTooth firmware, the patched ESP-BT controller is the attack radio' - 'For the availability test: an ESP32 broadband 2.4 GHz jammer (two nRF24L01+PA+LNA modules), operated only inside an RF-shielded / Faraday environment' software: - 'BrakTooth host tooling (Wireshark dissectors + the Python/ESP32 PoC firmware) to select and fire the LMP/baseband variants and read the target''s response' signal: - freq: '2.402–2.480 GHz (79 RF channels × 1 MHz, adaptive frequency hopping ~1600 hops/s)' + freq: '2.402 to 2.480 GHz (79 RF channels × 1 MHz, adaptive frequency hopping ~1600 hops/s)' bandwidth: '1 MHz per channel' modulation: 'GFSK 1 Mbps (Basic Rate); π/4-DQPSK 2 Mbps & 8DPSK 3 Mbps (EDR)' skill: advanced @@ -42,7 +42,7 @@ attacks: - cve-2021-28139 impact: >- Crash, deadlock or reboot of the BR/EDR controller across dozens of SoCs; - on at least one chip (ESP32, CVE-2021-28139) arbitrary code execution — all + on at least one chip (ESP32, CVE-2021-28139) arbitrary code execution, all reachable before pairing or authentication. preconditions: >- RF range to a target in connectable/page-scan mode and its BD_ADDR (or an @@ -51,21 +51,21 @@ attacks: summary: >- A directed-fuzzing-derived suite of ~20 baseband/Link Manager Protocol attack variants (16 vulnerabilities, 20+ CVEs assigned at disclosure) - against Bluetooth Classic controllers — the reference accessible BR/EDR + against Bluetooth Classic controllers, the reference accessible BR/EDR attack framework, running on a commodity ESP32. - name: Broadband 2.4 GHz jamming (availability) refs: - btcore-spec impact: >- - Wholesale denial of the 2.4 GHz ISM band — BR/EDR (all 79 channels), BLE - and Wi-Fi at once — measuring how the piconet behaves under RF denial + Wholesale denial of the 2.4 GHz ISM band, BR/EDR (all 79 channels), BLE + and Wi-Fi at once, measuring how the piconet behaves under RF denial (drop, reconnect storm, silent fallback). preconditions: >- An RF-shielded test environment; jamming is illegal in most jurisdictions outside a licensed/controlled lab. summary: >- Floods the band with noise to test availability of the link rather than - its protocol logic — the crude but informative DoS baseline against a + its protocol logic, the crude but informative DoS baseline against a frequency-hopping protocol that nominally tolerates interference. - name: KNOB (Key Negotiation of Bluetooth) cve: @@ -75,7 +75,7 @@ attacks: - cve-2019-9506 impact: >- Forces the negotiated link encryption key down to as little as 1 byte of - entropy, after which it is brute-forceable offline — enabling decryption + entropy, after which it is brute-forceable offline, enabling decryption and injection of valid ciphertext. A downgrade follow-on, not a baseband crash. preconditions: >- @@ -83,7 +83,7 @@ attacks: victims; the target must accept the low entropy the attacker requests. summary: >- A specification-level downgrade attack on the encryption key entropy - negotiation of Bluetooth BR/EDR — noted here as the natural follow-on once + negotiation of Bluetooth BR/EDR, noted here as the natural follow-on once the controller's resilience and key-size floor have been probed. - name: BIAS (Bluetooth Impersonation AttackS) cve: @@ -93,7 +93,7 @@ attacks: - cve-2020-10135 impact: >- Impersonation of a previously-paired BR/EDR master or slave, completing - authentication without the link key — combinable with KNOB to fully take + authentication without the link key, combinable with KNOB to fully take over an encrypted session. preconditions: >- A prior pairing between the two victims and an adjacent attacker that can @@ -101,7 +101,7 @@ attacks: mutual authentication and permissive role switching. summary: >- A standard-compliant impersonation attack abusing BR/EDR's authentication - procedure — the impersonation follow-on that pairs with KNOB; the + procedure, the impersonation follow-on that pairs with KNOB; the link-and-above assessment of it is owned by BSAM. references: - key: garbelini2022braktooth @@ -112,14 +112,14 @@ references: url: 'https://www.usenix.org/conference/usenixsecurity22/presentation/garbelini' type: paper - key: braktooth-site - title: 'BrakTooth — disclosure, affected-device list and CVE table' + title: 'BrakTooth, disclosure, affected-device list and CVE table' authors: ASSET Research Group, SUTD venue: braktooth.com year: 2021 url: 'https://braktooth.com/' type: blog - key: braktooth-repo - title: 'braktooth_esp32_bluetooth_classic_attacks — PoC firmware and host tooling' + title: 'braktooth_esp32_bluetooth_classic_attacks, PoC firmware and host tooling' authors: M. E. Garbelini (Matheus-Garbelini) venue: GitHub year: 2021 @@ -180,21 +180,21 @@ lastResearched: 2026-06-14 --- ## Mechanism -Bluetooth Classic (BR/EDR) is a different PHY/MAC from BLE: it hops across all 79 RF channels at ~1600 hops/s using GFSK (Basic Rate, 1 Mbps) and π/4-DQPSK / 8DPSK (EDR, 2–3 Mbps), and its low-level state machine is driven by the Link Manager Protocol (LMP) over the baseband. The attack surface this control exercises sits *below* pairing and authentication: a controller must parse paging, FHS, and LMP control PDUs from any device in range before it has decided whether to trust it. Malformed or out-of-sequence baseband/LMP traffic therefore reaches the controller firmware unauthenticated. +Bluetooth Classic (BR/EDR) is a different PHY/MAC from BLE: it hops across all 79 RF channels at ~1600 hops/s using GFSK (Basic Rate, 1 Mbps) and π/4-DQPSK / 8DPSK (EDR, 2 to 3 Mbps), and its low-level state machine is driven by the Link Manager Protocol (LMP) over the baseband. The attack surface this control exercises sits *below* pairing and authentication: a controller must parse paging, FHS, and LMP control PDUs from any device in range before it has decided whether to trust it. Malformed or out-of-sequence baseband/LMP traffic therefore reaches the controller firmware unauthenticated. -**BrakTooth** is the reference demonstration of this. Garbelini et al. applied directed fuzzing to the LMP/baseband state machine and found 16 vulnerabilities — 20+ attack variants, 20+ CVEs assigned at disclosure — that crash, deadlock, or reboot the BR/EDR controllers of dozens of SoCs from major vendors, and on at least one chip (the ESP32 itself, CVE-2021-28139) achieve arbitrary code execution (garbelini2022braktooth, braktooth-site). Crucially, every variant is reachable *before* pairing or authentication, and the whole suite runs from a $5 ESP32 acting as the attack radio (braktooth-repo). Treat the published CVE/affected-device table as representative of the LMP-parsing class, not a current patch matrix — vendor fix status varies and dates fast. +**BrakTooth** is the reference demonstration of this. Garbelini et al. applied directed fuzzing to the LMP/baseband state machine and found 16 vulnerabilities, 20+ attack variants, 20+ CVEs assigned at disclosure, that crash, deadlock, or reboot the BR/EDR controllers of dozens of SoCs from major vendors, and on at least one chip (the ESP32 itself, CVE-2021-28139) achieve arbitrary code execution (garbelini2022braktooth, braktooth-site). Crucially, every variant is reachable *before* pairing or authentication, and the whole suite runs from a $5 ESP32 acting as the attack radio (braktooth-repo). Treat the published CVE/affected-device table as representative of the LMP-parsing class, not a current patch matrix, vendor fix status varies and dates fast. -A **broadband 2.4 GHz jammer** tests a different property: availability rather than protocol logic. BR/EDR's adaptive frequency hopping is designed to tolerate narrowband interference, so wholesale noise across the band is the crude baseline for "does the link survive RF denial, and how does it fail" — drop, reconnect storm, or silent fallback to a weaker mode (btcore-spec). +A **broadband 2.4 GHz jammer** tests a different property: availability rather than protocol logic. BR/EDR's adaptive frequency hopping is designed to tolerate narrowband interference, so wholesale noise across the band is the crude baseline for "does the link survive RF denial, and how does it fail", drop, reconnect storm, or silent fallback to a weaker mode (btcore-spec). -Two specification-level follow-ons round out the active picture and are noted, not re-derived here: **KNOB** (CVE-2019-9506) downgrades the negotiated encryption key to as little as 1 byte of entropy so it can be brute-forced offline (antonioli2019knob, cve-2019-9506), and **BIAS** (CVE-2020-10135) impersonates a previously-paired peer by abusing BR/EDR's authentication procedure (antonioli2020bias, cve-2020-10135). The link-and-above assessment of those — pairing policy, encryption enforcement, key-size floor — is owned by BSAM (BSAM-IG-02 controller vulnerabilities, BSAM-EN-03 minimum encryption key size); RFSAM owns getting the active RF probe onto the controller in the first place. +Two specification-level follow-ons round out the active picture and are noted, not re-derived here: **KNOB** (CVE-2019-9506) downgrades the negotiated encryption key to as little as 1 byte of entropy so it can be brute-forced offline (antonioli2019knob, cve-2019-9506), and **BIAS** (CVE-2020-10135) impersonates a previously-paired peer by abusing BR/EDR's authentication procedure (antonioli2020bias, cve-2020-10135). The link-and-above assessment of those, pairing policy, encryption enforcement, key-size floor, is owned by BSAM (BSAM-IG-02 controller vulnerabilities, BSAM-EN-03 minimum encryption key size); RFSAM owns getting the active RF probe onto the controller in the first place. CVE-2021-28139 is the ESP32 arbitrary-code-execution variant specifically: the Espressif ESP-IDF Bluetooth Classic stack mishandles an LMP Feature Response Extended packet, letting an attacker in radio range run code via a crafted Extended Features bitfield (cve-2021-28139). The other BrakTooth variants are predominantly DoS (crash/deadlock/reboot). ## Procedure -> Authorised testing only. Every step below transmits in the 2.4 GHz ISM band and can crash, hang, reboot, or (on vulnerable chips) execute code on a live controller. Run only against devices you own or are explicitly contracted to assess. The jamming step is illegal in most jurisdictions outside a licensed/RF-shielded environment — perform it inside a Faraday cage or shielded room only, never over the air. +> Authorised testing only. Every step below transmits in the 2.4 GHz ISM band and can crash, hang, reboot, or (on vulnerable chips) execute code on a live controller. Run only against devices you own or are explicitly contracted to assess. The jamming step is illegal in most jurisdictions outside a licensed/RF-shielded environment, perform it inside a Faraday cage or shielded room only, never over the air. -1. Identify the target and confirm it speaks BR/EDR, and record its `BD_ADDR` (from an inquiry scan or prior IG/SP work — see `RFSAM-RES-26` for ESP32 inquiry scanning). You need the 48-bit address to direct the attack: +1. Identify the target and confirm it speaks BR/EDR, and record its `BD_ADDR` (from an inquiry scan or prior IG/SP work, see `RFSAM-RES-26` for ESP32 inquiry scanning). You need the 48-bit address to direct the attack: ```bash # target address recorded during inquiry, e.g. TARGET=AA:BB:CC:DD:EE:FF @@ -222,25 +222,25 @@ CVE-2021-28139 is the ESP32 arbitrary-code-execution variant specifically: the E ```bash l2ping -c 5 "$TARGET" # from a separate host: timeouts => link/controller down ``` - Record exactly which variant produced which behaviour (crash vs deadlock vs reboot vs RCE indicator) — that mapping is the finding. + Record exactly which variant produced which behaviour (crash vs deadlock vs reboot vs RCE indicator), that mapping is the finding. 5. Availability test (shielded environment only). With the target in a normal connected session inside the Faraday cage, enable the broadband jammer and observe how the link degrades and whether it recovers: ```bash # ESP32 broadband jammer: floods 2.4 GHz across BR/EDR, BLE and Wi-Fi - # (two nRF24L01+PA+LNA modules) — shielded lab only. + # (two nRF24L01+PA+LNA modules), shielded lab only. ``` Note whether the piconet drops cleanly, enters a reconnect storm, or silently falls back to a weaker mode. Disable the jammer and confirm the link re-establishes. -6. Note the downgrade/impersonation follow-ons (KNOB / BIAS) and the encryption-key-entropy test path (`RFSAM-RES-28`) as the next steps where the controller survived the baseband probes but its pairing/encryption policy is in scope — assess those under BSAM-EN-03 / BSAM-IG-02 rather than re-deriving them here. +6. Note the downgrade/impersonation follow-ons (KNOB / BIAS) and the encryption-key-entropy test path (`RFSAM-RES-28`) as the next steps where the controller survived the baseband probes but its pairing/encryption policy is in scope, assess those under BSAM-EN-03 / BSAM-IG-02 rather than re-deriving them here. ## Field case -[FILL: insert a real authorised engagement once available.] As an illustrative-only worked example (not a measured finding): a wireless point-of-sale handheld using an EDR controller was assessed in a shielded lab. From a single original ESP32 running BrakTooth, the `Feature_Response_Flooding` variant against the unit's `BD_ADDR` left it answering inquiry but unable to complete a new ACL connection — a soft deadlock requiring a power cycle to clear — while a separate `l2ping -c 5` from a laptop showed 5/5 timeouts, confirming the controller, not just the app, had stalled. No code-execution indicator was observed on this controller. Under the broadband jammer the active card-reader session dropped within ~[FILL: measured seconds] and re-paired automatically once jamming stopped, i.e. it failed available-but-recoverable rather than failing closed. Mark every concrete number here `[FILL: …]` until taken from a real capture — do not present the illustrative values as measured. +[FILL: insert a real authorised engagement once available.] As an illustrative-only worked example (not a measured finding): a wireless point-of-sale handheld using an EDR controller was assessed in a shielded lab. From a single original ESP32 running BrakTooth, the `Feature_Response_Flooding` variant against the unit's `BD_ADDR` left it answering inquiry but unable to complete a new ACL connection, a soft deadlock requiring a power cycle to clear, while a separate `l2ping -c 5` from a laptop showed 5/5 timeouts, confirming the controller, not just the app, had stalled. No code-execution indicator was observed on this controller. Under the broadband jammer the active card-reader session dropped within ~[FILL: measured seconds] and re-paired automatically once jamming stopped, i.e. it failed available-but-recoverable rather than failing closed. Mark every concrete number here `[FILL: …]` until taken from a real capture, do not present the illustrative values as measured. ## Remediation -**Developer / silicon & stack vendor.** Harden the LMP/baseband parser against malformed and out-of-sequence PDUs reachable before authentication — this is the BrakTooth root cause (garbelini2022braktooth). Track the BrakTooth CVE table and ship controller firmware updates; treat the published list as representative and re-check current advisories rather than assuming a chip is clear (braktooth-site). Reject the encryption-key-entropy downgrade by enforcing a minimum key size (closes KNOB, antonioli2019knob) and require mutual authentication / restrict role switching during connection establishment (closes BIAS, antonioli2020bias). +**Developer / silicon & stack vendor.** Harden the LMP/baseband parser against malformed and out-of-sequence PDUs reachable before authentication, this is the BrakTooth root cause (garbelini2022braktooth). Track the BrakTooth CVE table and ship controller firmware updates; treat the published list as representative and re-check current advisories rather than assuming a chip is clear (braktooth-site). Reject the encryption-key-entropy downgrade by enforcing a minimum key size (closes KNOB, antonioli2019knob) and require mutual authentication / restrict role switching during connection establishment (closes BIAS, antonioli2020bias). **Integrator.** Select controllers with a current patch level against the BrakTooth class and confirm the vendor's fix status before shipping (BSAM-IG-02). Enforce a minimum negotiated encryption key size in the host configuration (BSAM-EN-03) so a downgraded link is refused rather than accepted. -**Operator.** Where the device permits, disable discoverability/connectability when not actively pairing to shrink the unauthenticated attack surface, and monitor for unexplained controller reboots or repeated reconnects — the observable signature of baseband/LMP fuzzing or jamming in the field. For availability-critical Bluetooth Classic links, plan for graceful degradation: assume the 2.4 GHz band can be denied and ensure loss of the link fails safe. +**Operator.** Where the device permits, disable discoverability/connectability when not actively pairing to shrink the unauthenticated attack surface, and monitor for unexplained controller reboots or repeated reconnects, the observable signature of baseband/LMP fuzzing or jamming in the field. For availability-critical Bluetooth Classic links, plan for graceful degradation: assume the 2.4 GHz band can be denied and ensure loss of the link fails safe. diff --git a/src/content/controls/rfsam-btc-cr-01.md b/src/content/controls/rfsam-btc-cr-01.md index 49636b7..890046a 100644 --- a/src/content/controls/rfsam-btc-cr-01.md +++ b/src/content/controls/rfsam-btc-cr-01.md @@ -9,7 +9,7 @@ applicability: deferred: true objective: >- Determine whether a Bluetooth Classic (BR/EDR) link's confidentiality can be - broken or downgraded — recovering a legacy-PIN link key offline from a captured + broken or downgraded, recovering a legacy-PIN link key offline from a captured pairing, exploiting Secure Simple Pairing "Just Works" (no MITM protection), or forcing the negotiated encryption key down to brute-forceable entropy (KNOB) and impersonating a paired peer without the link key (BIAS). @@ -18,11 +18,11 @@ intro: >- entropy of the negotiated encryption key. Legacy PIN pairing seeds the link key from a short/fixed PIN that falls to an offline brute force on a captured pairing; Secure Simple Pairing resists offline key recovery but its "Just Works" - model has no MITM protection; and two protocol-level flaws — KNOB + model has no MITM protection; and two protocol-level flaws, KNOB (encryption-key-entropy downgrade, CVE-2019-9506) and BIAS (impersonation of a - paired peer, CVE-2020-10135) — undercut even SSP links. RFSAM owns the - RF-capture prerequisite — getting the pairing/authentication exchange off the - air into a dissector — while the judgement on rejecting legacy pairing and + paired peer, CVE-2020-10135), undercut even SSP links. RFSAM owns the + RF-capture prerequisite, getting the pairing/authentication exchange off the + air into a dissector, while the judgement on rejecting legacy pairing and enforcing a minimum encryption key size is assessed under BSAM (BSAM-PA-04, BSAM-EN-03). prerequisites: @@ -31,7 +31,7 @@ prerequisites: software: - 'BTSnifferBREDR.py host tool (Scapy/Wireshark output) for capture; Wireshark to dissect the LMP exchange; offline analysis for legacy-PIN link-key recovery (Shaked & Wool method) and KNOB/BIAS assessment of the negotiated key size and authentication flow' signal: - freq: '2.402–2.480 GHz (79 RF channels × 1 MHz, adaptive frequency hopping ~1600 hops/s)' + freq: '2.402 to 2.480 GHz (79 RF channels × 1 MHz, adaptive frequency hopping ~1600 hops/s)' bandwidth: '1 MHz per channel' modulation: 'GFSK 1 Mbps (Basic Rate); π/4-DQPSK 2 Mbps & 8DPSK 3 Mbps (EDR)' skill: advanced @@ -63,11 +63,11 @@ attacks: decryption of the ciphertext and injection of valid encrypted frames. preconditions: >- An attacker in radio range during encryption setup; a flaw in the BR/EDR - specification (v1.0–5.1), so it is largely implementation-independent. + specification (v1.0 to 5.1), so it is largely implementation-independent. Devices that enforce a minimum key size reject the downgrade. summary: >- The BR/EDR encryption-key negotiation lets a man-in-the-middle lower the - key entropy to 1 byte without either victim noticing — a downgrade, not a + key entropy to 1 byte without either victim noticing, a downgrade, not a cryptographic break. - name: BIAS (Bluetooth Impersonation AttackS) cve: @@ -122,7 +122,7 @@ references: url: 'https://nvd.nist.gov/vuln/detail/CVE-2020-10135' type: cve - key: knob-poc-internalblue - title: 'KNOB attack PoC (InternalBlue) — sample-nexmaster-galaxys9slave.pcapng' + title: 'KNOB attack PoC (InternalBlue), sample-nexmaster-galaxys9slave.pcapng' authors: D. Antonioli venue: 'francozappa/knob, poc-internalblue' url: 'https://github.com/francozappa/knob/blob/master/poc-internalblue/README.md' @@ -144,21 +144,21 @@ lastResearched: 2026-06-14 Bluetooth Classic confidentiality depends on two things: which association model derived the link key, and how much entropy the link encryption key carries. The KNOB authors frame both as protocol-level, not implementation-level, problems (antonioli2019knob). -**Legacy PIN pairing.** In legacy pairing a PIN seeds the link key through the SAFER+ key derivation. Because the PIN is often short or fixed (`0000`, `1234`), a passive attacker who captures the pairing exchange (the `IN_RAND`, `COMB_KEY` and `AU_RAND`/`SRES` messages) can replay the derivation offline and brute-force the PIN — Shaked & Wool cracked a 4-digit PIN in well under a second on 2005-era hardware, recovering the link key and hence the session (shaked2005pin). This requires capturing the pairing, and modern devices rarely use legacy pairing. +**Legacy PIN pairing.** In legacy pairing a PIN seeds the link key through the SAFER+ key derivation. Because the PIN is often short or fixed (`0000`, `1234`), a passive attacker who captures the pairing exchange (the `IN_RAND`, `COMB_KEY` and `AU_RAND`/`SRES` messages) can replay the derivation offline and brute-force the PIN, Shaked & Wool cracked a 4-digit PIN in well under a second on 2005-era hardware, recovering the link key and hence the session (shaked2005pin). This requires capturing the pairing, and modern devices rarely use legacy pairing. -**Secure Simple Pairing (SSP).** SSP uses ECDH (P-192 in 2.1, P-256 in 4.1+) and resists offline key recovery. Its weak point is the **Just Works** association model, which has no MITM protection — an active man-in-the-middle problem rather than an offline crack. Establishing which SSP association model is in use (Just Works vs Passkey vs OOB) is the observable finding RFSAM contributes; the policy judgement is BSAM's (BSAM-PA-04). +**Secure Simple Pairing (SSP).** SSP uses ECDH (P-192 in 2.1, P-256 in 4.1+) and resists offline key recovery. Its weak point is the **Just Works** association model, which has no MITM protection, an active man-in-the-middle problem rather than an offline crack. Establishing which SSP association model is in use (Just Works vs Passkey vs OOB) is the observable finding RFSAM contributes; the policy judgement is BSAM's (BSAM-PA-04). **KNOB (CVE-2019-9506).** Independent of pairing model, the BR/EDR encryption-key-size negotiation lets a man-in-the-middle force the entropy down to as little as 1 byte without either victim being alerted; the key is then brute-forced in real time, the ciphertext decrypted and valid encrypted frames injected. NVD records this as the spec (up to v5.1) permitting a low key length and not preventing an attacker from influencing the negotiation (antonioli2019knob, cve-2019-9506). The defence is a host-enforced minimum key size (BSAM-EN-03). **BIAS (CVE-2020-10135).** BIAS abuses the BR/EDR authentication procedure and a role switch to impersonate a previously-paired master or slave and complete authentication without the link key; it composes with KNOB to attack Secure Connections links as well (antonioli2020bias, cve-2020-10135). -This CVE coverage is representative, not exhaustive — KNOB and BIAS are spec-level flaws demonstrated across many BR/EDR chips, but patch status varies by vendor and firmware. Confirm against current advisories and the device's BR/EDR controller firmware before asserting a given target is or is not affected. +This CVE coverage is representative, not exhaustive, KNOB and BIAS are spec-level flaws demonstrated across many BR/EDR chips, but patch status varies by vendor and firmware. Confirm against current advisories and the device's BR/EDR controller firmware before asserting a given target is or is not affected. -RFSAM's job at this floor is the RF-capture prerequisite — getting the LMP pairing/authentication exchange off the air and into a dissector — after which the pairing-policy and key-size verdicts are assessed under BSAM. There is no clean point-and-click ESP32 tool for the offline cracking step, so this floor is mostly analysis of the capture from the link layer plus the BSAM pairing controls. +RFSAM's job at this floor is the RF-capture prerequisite, getting the LMP pairing/authentication exchange off the air and into a dissector, after which the pairing-policy and key-size verdicts are assessed under BSAM. There is no clean point-and-click ESP32 tool for the offline cracking step, so this floor is mostly analysis of the capture from the link layer plus the BSAM pairing controls. ## Procedure -> All active capture and any decryption/downgrade steps below are authorised-testing only: run them against your own devices or a target you are explicitly contracted to assess, in an RF-shielded or controlled environment, with test devices and recorded permission. The ESP32 baseband sniffer actively connects to follow the target — it is not purely passive. +> All active capture and any decryption/downgrade steps below are authorised-testing only: run them against your own devices or a target you are explicitly contracted to assess, in an RF-shielded or controlled environment, with test devices and recorded permission. The ESP32 baseband sniffer actively connects to follow the target, it is not purely passive. 1. Confirm the target is Bluetooth Classic (BR/EDR), not BLE, and note its `BD_ADDR` and Class of Device from the inquiry-scan step (see the SP-layer enumeration; RFSAM-RES-27 sets up the same BR/EDR kit). @@ -177,7 +177,7 @@ RFSAM's job at this floor is the RF-capture prerequisite — getting the LMP pai Read off the association model and key sizes: - Legacy PIN pairing shows `LMP_in_rand` / `LMP_comb_key` / `LMP_au_rand` / `LMP_sres`. - SSP shows the `LMP_encapsulated_*` / IO-capability exchange; identify Just Works vs Passkey vs OOB. - - The encryption-key-size negotiation is `LMP_encryption_key_size_req` — record the **negotiated key length in bytes**. A value driven to 1 byte is the KNOB signature. + - The encryption-key-size negotiation is `LMP_encryption_key_size_req`, record the **negotiated key length in bytes**. A value driven to 1 byte is the KNOB signature. 4. Classify the finding: - **Negotiated key size < the device's policy minimum (e.g. forced to 1 byte):** KNOB-style downgrade is feasible (antonioli2019knob, cve-2019-9506). Defer the minimum-key-size verdict to BSAM-EN-03. @@ -188,12 +188,12 @@ RFSAM's job at this floor is the RF-capture prerequisite — getting the LMP pai ## Field case -The reference KNOB sample capture shipped by the attack's authors (francozappa/knob, `poc-internalblue/sample-nexmaster-galaxys9slave.pcapng` — a Nexus 5 master and a Galaxy S9 slave) shows exactly this signature, captured before any KNOB patch was released [knob-poc-internalblue]. Opening it in Wireshark and isolating the Link Manager exchange with the `btbrlmp` filter, the `LMP_encryption_key_size_req` negotiation in packets 121–127 settles on **1 byte** of entropy — 8 bits, the minimum the BR/EDR specification permits — with neither device objecting to the downgrade [knob-poc-internalblue]. The documented finding is the KNOB signature: *the encryption key size is negotiated down below any safe policy minimum*, after which the 1-byte key is brute-forced in real time and the session ciphertext decrypted (antonioli2019knob, cve-2019-9506). The exploitability verdict — that the host accepted an encryption key entropy far below policy — is exactly what RFSAM gets off the air here; enforcing a minimum encryption key size is deferred to BSAM-EN-03, and rejecting legacy pairing to BSAM-PA-04. The same `btbrlmp` read-off applies unchanged to any BR/EDR link, from car hands-free units to HID peripherals. +The reference KNOB sample capture shipped by the attack's authors (francozappa/knob, `poc-internalblue/sample-nexmaster-galaxys9slave.pcapng`, a Nexus 5 master and a Galaxy S9 slave) shows exactly this signature, captured before any KNOB patch was released [knob-poc-internalblue]. Opening it in Wireshark and isolating the Link Manager exchange with the `btbrlmp` filter, the `LMP_encryption_key_size_req` negotiation in packets 121 to 127 settles on **1 byte** of entropy, 8 bits, the minimum the BR/EDR specification permits, with neither device objecting to the downgrade [knob-poc-internalblue]. The documented finding is the KNOB signature: *the encryption key size is negotiated down below any safe policy minimum*, after which the 1-byte key is brute-forced in real time and the session ciphertext decrypted (antonioli2019knob, cve-2019-9506). The exploitability verdict, that the host accepted an encryption key entropy far below policy, is exactly what RFSAM gets off the air here; enforcing a minimum encryption key size is deferred to BSAM-EN-03, and rejecting legacy pairing to BSAM-PA-04. The same `btbrlmp` read-off applies unchanged to any BR/EDR link, from car hands-free units to HID peripherals. ## Remediation -**Developer / firmware:** Reject legacy PIN pairing entirely and require Secure Simple Pairing with an authenticated association model (Passkey or OOB), never Just Works, for anything trust-bearing (BSAM-PA-04). Enforce a host-side minimum encryption key size and refuse links that negotiate below it — this is the direct defence against KNOB (BSAM-EN-03, cve-2019-9506). Where the controller and host support it, require Secure Connections (P-256) and refuse fallback to legacy authentication, which closes the BIAS legacy path (antonioli2020bias). +**Developer / firmware:** Reject legacy PIN pairing entirely and require Secure Simple Pairing with an authenticated association model (Passkey or OOB), never Just Works, for anything trust-bearing (BSAM-PA-04). Enforce a host-side minimum encryption key size and refuse links that negotiate below it, this is the direct defence against KNOB (BSAM-EN-03, cve-2019-9506). Where the controller and host support it, require Secure Connections (P-256) and refuse fallback to legacy authentication, which closes the BIAS legacy path (antonioli2020bias). -**Integrator:** Select BR/EDR controllers whose firmware patches the KNOB and BIAS classes, and verify the minimum-key-size enforcement is actually applied at the host (BlueZ `min_key_size` / equivalent), not just declared. Treat the KNOB/BIAS CVE list as representative — check the device's controller firmware against current vendor advisories. +**Integrator:** Select BR/EDR controllers whose firmware patches the KNOB and BIAS classes, and verify the minimum-key-size enforcement is actually applied at the host (BlueZ `min_key_size` / equivalent), not just declared. Treat the KNOB/BIAS CVE list as representative, check the device's controller firmware against current vendor advisories. **Operator:** Avoid pairing trust-bearing devices in untrusted RF environments; prefer OOB pairing where available; and where a device only offers legacy pairing or Just Works, treat its link as unauthenticated and do not place trust above it (BSAM-PA-04). diff --git a/src/content/controls/rfsam-btc-ig-01.md b/src/content/controls/rfsam-btc-ig-01.md index ed5b3be..6c7bedb 100644 --- a/src/content/controls/rfsam-btc-ig-01.md +++ b/src/content/controls/rfsam-btc-ig-01.md @@ -11,7 +11,7 @@ deferred: true objective: >- Determine whether the target speaks Bluetooth Classic (BR/EDR) versus LE-only versus dual-mode, fingerprint the controller SoC and host stack, and check the - published Bluetooth-Classic vulnerability corpus — using the RF prerequisite + published Bluetooth-Classic vulnerability corpus, using the RF prerequisite (confirming BR/EDR and reading BD_ADDR / Class of Device from an inquiry scan) to feed the BSAM Information-Gathering controls. intro: >- @@ -25,12 +25,12 @@ intro: >- work from. prerequisites: hardware: - - 'An original ESP32 (DevKit) — its controller has a real BR/EDR radio, so it can run a true Bluetooth Classic inquiry. An ESP32-S3/C-series is LE-only and cannot.' + - 'An original ESP32 (DevKit), its controller has a real BR/EDR radio, so it can run a true Bluetooth Classic inquiry. An ESP32-S3/C-series is LE-only and cannot.' - 'Optional: the device label / FCC ID and a teardown for the controller SoC part number.' software: - 'esp32-classic-bt-scan firmware (BR/EDR inquiry) or esp32-bt-exp (dual-mode discovery dump); an FCC-ID / teardown lookup for the chipset.' signal: - freq: '2.402–2.480 GHz (79 RF channels × 1 MHz, adaptive frequency hopping ~1600 hops/s)' + freq: '2.402 to 2.480 GHz (79 RF channels × 1 MHz, adaptive frequency hopping ~1600 hops/s)' bandwidth: '1 MHz per RF channel' modulation: 'GFSK 1 Mbps (Basic Rate); π/4-DQPSK 2 Mbps & 8DPSK 3 Mbps (EDR)' skill: beginner @@ -43,7 +43,7 @@ attacks: - armis2017blueborne impact: >- Remote code execution in kernel space via a stack overflow in L2CAP - configuration-response processing in the Linux BlueZ stack — reachable + configuration-response processing in the Linux BlueZ stack, reachable over the air with no pairing and no user interaction. preconditions: >- Target host runs an affected, unpatched native Bluetooth stack (the BlueZ @@ -77,7 +77,7 @@ attacks: - antonioli2020bias - cve-2020-10135 impact: >- - Impersonation of a previously-paired BR/EDR device — an adjacent attacker + Impersonation of a previously-paired BR/EDR device, an adjacent attacker completes authentication without the link key, taking either the master or slave role. preconditions: >- @@ -96,7 +96,7 @@ attacks: impact: >- Crashes, deadlocks and, on some SoCs, remote code execution against the BR/EDR controller via malformed baseband / Link Manager Protocol (LMP) - frames — ~16 CVEs and 20+ variants across dozens of Bluetooth-Classic + frames, ~16 CVEs and 20+ variants across dozens of Bluetooth-Classic chips. preconditions: >- Target uses an affected, unpatched BR/EDR controller SoC; attacker within @@ -154,7 +154,7 @@ references: url: 'https://asset-group.github.io/disclosures/braktooth/braktooth.pdf' type: paper - key: braktooth-repo - title: 'braktooth_esp32_bluetooth_classic_attacks — Baseband & LMP exploits against BR/EDR controllers' + title: 'braktooth_esp32_bluetooth_classic_attacks, Baseband & LMP exploits against BR/EDR controllers' authors: M. E. Garbelini venue: GitHub year: 2021 @@ -175,19 +175,19 @@ lastResearched: 2026-06-14 --- ## Mechanism -Before any RF work against a Bluetooth device, two questions decide everything that follows: **is this device even Bluetooth Classic (BR/EDR), and what silicon and stack run it?** Bluetooth Classic (BR/EDR) is a different PHY and MAC from Bluetooth Low Energy — it hops across 79 RF channels of 1 MHz at ~1600 hops/s with GFSK at 1 Mbps (Basic Rate) and π/4-DQPSK / 8DPSK at 2–3 Mbps (EDR), where BLE uses 40 channels and a different access scheme. The two share the 2.4 GHz band but **must never be conflated**: an ESP32-S3, nRF or CC-series target is usually LE-only and belongs on the BLE descent, while audio gear, HID peripherals, OBD-II dongles and car/infotainment modules are typically Classic or dual-mode. Confirming BR/EDR is therefore the first RF prerequisite this control owns. +Before any RF work against a Bluetooth device, two questions decide everything that follows: **is this device even Bluetooth Classic (BR/EDR), and what silicon and stack run it?** Bluetooth Classic (BR/EDR) is a different PHY and MAC from Bluetooth Low Energy, it hops across 79 RF channels of 1 MHz at ~1600 hops/s with GFSK at 1 Mbps (Basic Rate) and π/4-DQPSK / 8DPSK at 2 to 3 Mbps (EDR), where BLE uses 40 channels and a different access scheme. The two share the 2.4 GHz band but **must never be conflated**: an ESP32-S3, nRF or CC-series target is usually LE-only and belongs on the BLE descent, while audio gear, HID peripherals, OBD-II dongles and car/infotainment modules are typically Classic or dual-mode. Confirming BR/EDR is therefore the first RF prerequisite this control owns. A large share of real-world Bluetooth-Classic compromise is not a novel cryptographic break but an *unpatched* component carrying a known, named, CVE-tracked flaw. The flaw lives in one of three places, and identifying which is the whole point of this step: - **The controller (the BR/EDR SoC / radio firmware).** BrakTooth is the canonical Classic example: a family of ~16 CVEs and 20+ variants found by directed fuzzing of the baseband and Link Manager Protocol (LMP), causing crashes, deadlocks and, on some chips, remote code execution across dozens of BR/EDR controllers [garbelini2022braktooth]. The public proof-of-concept runs on the same cheap ESP32 used here [braktooth-repo]. This is a controller-vulnerability case under BSAM-IG-02. - **The host stack (the OS Bluetooth implementation).** BlueBorne is the canonical Classic example: a stack overflow in L2CAP configuration-response processing in the Linux BlueZ native stack (kernel 2.6.32 up to and including 4.13.1) yields kernel-space remote code execution over the air, with no pairing and no user interaction (CVE-2017-1000251) [cve-2017-1000251][armis2017blueborne]. This is a host-stack-vulnerability case under BSAM-IG-03. -- **The standard itself**, independent of any one chip. KNOB downgrades BR/EDR encryption-key entropy to as little as one byte during negotiation, making the session key brute-forceable (CVE-2019-9506) [antonioli2019knob][cve-2019-9506]. BIAS impersonates a previously-paired BR/EDR device by completing authentication without the link key (CVE-2020-10135, Core Specification v5.2 and earlier) [antonioli2020bias][cve-2020-10135]; the two chain naturally — downgrade with KNOB, then impersonate with BIAS. These are standard-vulnerability cases under BSAM-IG-04. +- **The standard itself**, independent of any one chip. KNOB downgrades BR/EDR encryption-key entropy to as little as one byte during negotiation, making the session key brute-forceable (CVE-2019-9506) [antonioli2019knob][cve-2019-9506]. BIAS impersonates a previously-paired BR/EDR device by completing authentication without the link key (CVE-2020-10135, Core Specification v5.2 and earlier) [antonioli2020bias][cve-2020-10135]; the two chain naturally, downgrade with KNOB, then impersonate with BIAS. These are standard-vulnerability cases under BSAM-IG-04. -BSAM already provides mature, dedicated controls for exactly this triage: controller vulnerabilities (BSAM-IG-02), host-stack vulnerabilities (BSAM-IG-03), and standard vulnerabilities (BSAM-IG-04). **RFSAM does not re-derive them.** This control exists to place the step in the RF assessment flow and to supply the one thing the RF assessor is best positioned to produce: confirmation that the device is BR/EDR, and its BD_ADDR (48-bit, with the upper 24 bits an OUI/vendor hint) and Class of Device read straight from an inquiry response — the component-inventory seed the BSAM controls consume. The named corpus above (BlueBorne, KNOB, BIAS, BrakTooth) is **representative, not exhaustive** — it dates fast, so always check current vendor advisories and the Bluetooth SIG erratum feed against the components you actually identify. +BSAM already provides mature, dedicated controls for exactly this triage: controller vulnerabilities (BSAM-IG-02), host-stack vulnerabilities (BSAM-IG-03), and standard vulnerabilities (BSAM-IG-04). **RFSAM does not re-derive them.** This control exists to place the step in the RF assessment flow and to supply the one thing the RF assessor is best positioned to produce: confirmation that the device is BR/EDR, and its BD_ADDR (48-bit, with the upper 24 bits an OUI/vendor hint) and Class of Device read straight from an inquiry response, the component-inventory seed the BSAM controls consume. The named corpus above (BlueBorne, KNOB, BIAS, BrakTooth) is **representative, not exhaustive**, it dates fast, so always check current vendor advisories and the Bluetooth SIG erratum feed against the components you actually identify. ## Procedure -> Steps below are passive identification (an inquiry scan and label inspection — no pairing, no connection, no transmission beyond the standard inquiry the controller performs). Run them only against devices you are authorised to assess. +> Steps below are passive identification (an inquiry scan and label inspection, no pairing, no connection, no transmission beyond the standard inquiry the controller performs). Run them only against devices you are authorised to assess. 1. **Read the silicon off the label / FCC ID.** Find the FCC ID on the device and look it up; the internal photos and test report usually name the module or controller SoC. ```bash @@ -196,46 +196,46 @@ BSAM already provides mature, dedicated controls for exactly this triage: contro ``` Expected: the module/chip part number (for example a CSR/Qualcomm, Cypress, Espressif, Realtek or Texas Instruments BR/EDR part), which maps directly onto the BSAM-IG-02 controller-vulnerability lookup. -2. **Confirm BR/EDR and capture BD_ADDR + Class of Device with an inquiry scan.** Flash the BR/EDR inquiry firmware to an *original* ESP32 (DevKit) and run a Classic inquiry — this uses the ESP32's own Bluetooth controller, the cheapest accessible way to enumerate Classic devices in range (RFSAM-RES-26). +2. **Confirm BR/EDR and capture BD_ADDR + Class of Device with an inquiry scan.** Flash the BR/EDR inquiry firmware to an *original* ESP32 (DevKit) and run a Classic inquiry, this uses the ESP32's own Bluetooth controller, the cheapest accessible way to enumerate Classic devices in range (RFSAM-RES-26). ```bash # esp32-classic-bt-scan: BR/EDR inquiry on the ESP32's own controller esptool.py --chip esp32 write_flash 0x0 esp32-classic-bt-scan.bin # then open the serial monitor at 115200 baud to read the inquiry results ``` - Expected (per discoverable device): a `BD_ADDR`, friendly name, RSSI and a `Class of Device` (CoD). A device answering this BR/EDR inquiry is, by definition, Classic-capable — that is the confirmation this control needs. The 48-bit BD_ADDR's upper 24 bits are an OUI you can resolve to a vendor; the CoD's major/minor fields hint at the device type (audio, peripheral, phone). A device that never answers a Classic inquiry but does answer a BLE scan is LE-only — send it to the BLE descent (RFSAM-BLE-IG-01). + Expected (per discoverable device): a `BD_ADDR`, friendly name, RSSI and a `Class of Device` (CoD). A device answering this BR/EDR inquiry is, by definition, Classic-capable, that is the confirmation this control needs. The 48-bit BD_ADDR's upper 24 bits are an OUI you can resolve to a vendor; the CoD's major/minor fields hint at the device type (audio, peripheral, phone). A device that never answers a Classic inquiry but does answer a BLE scan is LE-only, send it to the BLE descent (RFSAM-BLE-IG-01). 3. **Disambiguate dual-mode when a target could be either.** If the device might expose both radios, bring up the dual-mode discovery dump (`esp32-bt-exp`) to list what it sees on Classic (inquiry) and BLE at once. ```bash # esp32-bt-exp: Bluedroid dual-mode discovery dump (Classic + BLE survey) esptool.py --chip esp32 write_flash 0x0 esp32-bt-exp.bin ``` - Expected: a combined survey. A device appearing in *both* the Classic and BLE lists is dual-mode (BR/EDR + LE) — note this, because the two radios are assessed on different descents and a finding on one does not imply the other. + Expected: a combined survey. A device appearing in *both* the Classic and BLE lists is dual-mode (BR/EDR + LE), note this, because the two radios are assessed on different descents and a finding on one does not imply the other. -4. **Infer the controller / host-stack / spec-version tuple.** Combine the BD_ADDR OUI and CoD from step 2 with the FCC-ID/teardown part number from step 1, and with the host behind the device where known (a phone or Linux gateway implies its stack — for example Android Fluoride, Linux BlueZ). The Core-Spec version it claims bounds the spec-level corpus (KNOB ≤ 5.1; BIAS ≤ 5.2). - Expected: a `(controller SoC, host stack, Core-Spec version)` tuple — the input the BSAM-IG controls need. +4. **Infer the controller / host-stack / spec-version tuple.** Combine the BD_ADDR OUI and CoD from step 2 with the FCC-ID/teardown part number from step 1, and with the host behind the device where known (a phone or Linux gateway implies its stack, for example Android Fluoride, Linux BlueZ). The Core-Spec version it claims bounds the spec-level corpus (KNOB ≤ 5.1; BIAS ≤ 5.2). + Expected: a `(controller SoC, host stack, Core-Spec version)` tuple, the input the BSAM-IG controls need. 5. **Run the BSAM Information-Gathering controls against the identified components.** This is where the judgement is made; RFSAM hands off here. - - **BSAM-IG-02** — controller vulnerabilities (for example BrakTooth against the identified BR/EDR SoC). - - **BSAM-IG-03** — host-stack vulnerabilities (for example BlueBorne against the identified native stack). - - **BSAM-IG-04** — standard vulnerabilities (for example KNOB / BIAS against the claimed Core-Spec version). + - **BSAM-IG-02**, controller vulnerabilities (for example BrakTooth against the identified BR/EDR SoC). + - **BSAM-IG-03**, host-stack vulnerabilities (for example BlueBorne against the identified native stack). + - **BSAM-IG-04**, standard vulnerabilities (for example KNOB / BIAS against the claimed Core-Spec version). -6. **Carry the result forward as scoping input** to the RFSAM SP/PHY/LL capture controls. An end-of-life, unpatchable controller with a published BrakTooth RCE may make further dynamic RF testing moot — that finding is already decisive. +6. **Carry the result forward as scoping input** to the RFSAM SP/PHY/LL capture controls. An end-of-life, unpatchable controller with a published BrakTooth RCE may make further dynamic RF testing moot, that finding is already decisive. ## Field case -Illustrative walkthrough — substitute the values you capture. The target is a Bluetooth-Classic hands-free car module: +Illustrative walkthrough, substitute the values you capture. The target is a Bluetooth-Classic hands-free car module: - **Step 1 (label):** the FCC ID's internal photos showed a [FILL: controller SoC part number read from the FCC internal photos / teardown], placing the controller on the BSAM-IG-02 lookup. -- **Step 2 (air):** the `esp32-classic-bt-scan` inquiry returned the unit answering a BR/EDR inquiry — confirming Classic, not LE-only — with `BD_ADDR [FILL: 48-bit address from the inquiry response]`, a friendly name matching the head unit, and a Class of Device with the Audio major class set. The BD_ADDR's upper-24-bit OUI resolved to the module vendor, consistent with the label. -- **Step 3 (dual-mode):** `esp32-bt-exp` showed the same unit on the Classic list only and not on BLE — a Classic-only target, so the assessment stays on the BR/EDR descent. +- **Step 2 (air):** the `esp32-classic-bt-scan` inquiry returned the unit answering a BR/EDR inquiry, confirming Classic, not LE-only, with `BD_ADDR [FILL: 48-bit address from the inquiry response]`, a friendly name matching the head unit, and a Class of Device with the Audio major class set. The BD_ADDR's upper-24-bit OUI resolved to the module vendor, consistent with the label. +- **Step 3 (dual-mode):** `esp32-bt-exp` showed the same unit on the Classic list only and not on BLE, a Classic-only target, so the assessment stays on the BR/EDR descent. - **Step 5 (BSAM):** running BSAM-IG-02/IG-04 against the identified controller and its claimed Core-Spec version is the decisive step. If the controller predates the vendor's BrakTooth fix, the unit is exposed to the relevant baseband/LMP crash-or-RCE variant regardless of how strong the pairing *looks*; if it claims Core Spec ≤ 5.1, KNOB applies at the standard level. -The value RFSAM adds here is sequencing, not a new finding: the cheap inquiry-scan component inventory from this step scopes which SP/PHY/LL capture controls are worth running at all. The `[FILL: …]` placeholders (controller part number, BD_ADDR) are intentional — replace them only with values actually read from a device before claiming a specific finding. +The value RFSAM adds here is sequencing, not a new finding: the cheap inquiry-scan component inventory from this step scopes which SP/PHY/LL capture controls are worth running at all. The `[FILL: …]` placeholders (controller part number, BD_ADDR) are intentional, replace them only with values actually read from a device before claiming a specific finding. ## Remediation **Developer (device firmware / controller integration).** Track your BR/EDR controller vendor's advisory feed and the Bluetooth SIG erratum feed; ship the controller-firmware fixes for the named flaws (BrakTooth baseband/LMP) [garbelini2022braktooth]. Reject low encryption-key entropy to defeat KNOB-style downgrade and set a high minimum key size [antonioli2019knob][cve-2019-9506]. Enforce mutual re-authentication that re-derives the link key, closing the BIAS impersonation class [antonioli2020bias][cve-2020-10135]. Do not select an end-of-life BR/EDR controller with no patch path for a new design. -**Integrator (host / OS stack).** Keep the host Bluetooth stack patched — BlueBorne (CVE-2017-1000251) is a kernel/BlueZ fix, so patch the kernel, not just the application [cve-2017-1000251]. Disable BR/EDR discoverability and Classic profiles that are not in use, shrinking the inquiry-visible surface this control fingerprints. +**Integrator (host / OS stack).** Keep the host Bluetooth stack patched, BlueBorne (CVE-2017-1000251) is a kernel/BlueZ fix, so patch the kernel, not just the application [cve-2017-1000251]. Disable BR/EDR discoverability and Classic profiles that are not in use, shrinking the inquiry-visible surface this control fingerprints. **Operator (deployment / fleet).** Maintain a per-device component inventory (controller SoC + host stack + Core-Spec version) keyed off the BD_ADDR, so a newly published Classic CVE can be matched to the fleet quickly. Treat any controller that is end-of-life with no patch path as high-risk and plan replacement. Follow the remediation of the cited BSAM Information-Gathering controls (BSAM-IG-02/03/04), which own the formal judgement this control defers to. diff --git a/src/content/controls/rfsam-btc-ll-01.md b/src/content/controls/rfsam-btc-ll-01.md index 078af7c..eb5b8b8 100644 --- a/src/content/controls/rfsam-btc-ll-01.md +++ b/src/content/controls/rfsam-btc-ll-01.md @@ -9,27 +9,27 @@ applicability: deferred: false objective: >- Determine whether Bluetooth Classic (BR/EDR) baseband frames can be pulled off - the air into a dissector on commodity hardware — getting the BT header, + the air into a dissector on commodity hardware, getting the BT header, channel, role, FHS, ACL and LMP of a live piconet into Wireshark/Scapy so the link-and-above assessment can begin. intro: >- A software-defined radio cannot follow a BR/EDR piconet hopping ~1600 times a second across 79 channels, so the accessible capture path uses a device that owns a real Bluetooth controller. The reference option is the Garbelini ESP32 - BR/EDR sniffer — it patches the chip's ROM Bluetooth stack to dump baseband + BR/EDR sniffer, it patches the chip's ROM Bluetooth stack to dump baseband packets over USB serial into Wireshark/Scapy; the Ubertooth One is a legacy, partial Basic-Rate option. RFSAM owns this RF-capture floor and feeds the resulting frames to BSAM's link-and-above controls. prerequisites: hardware: - - 'An original ESP32 (BR/EDR-capable Classic radio — not an ESP32-S3/C-series, which are LE-only), e.g. ESP32-DOIT (~$4) or ESP32-DevKitC (~$10)' + - 'An original ESP32 (BR/EDR-capable Classic radio, not an ESP32-S3/C-series, which are LE-only), e.g. ESP32-DOIT (~$4) or ESP32-DevKitC (~$10)' - 'Optionally an Ubertooth One for legacy partial Basic-Rate capture' software: - 'The Garbelini esp32_bluetooth_classic_sniffer firmware + BTSnifferBREDR.py host tool (Scapy, with the h4bcm Wireshark dissector)' - 'Ubertooth host tools (ubertooth-rx) + libbtbb for the legacy path' - 'Wireshark for dissection' signal: - freq: '2.402–2.480 GHz (79 RF channels × 1 MHz, adaptive frequency hopping ~1600 hops/s)' + freq: '2.402 to 2.480 GHz (79 RF channels × 1 MHz, adaptive frequency hopping ~1600 hops/s)' bandwidth: '1 MHz per channel' modulation: 'GFSK 1 Mbps (Basic Rate); π/4-DQPSK 2 Mbps & 8DPSK 3 Mbps (EDR)' skill: intermediate @@ -40,8 +40,8 @@ attacks: - braktooth-repo impact: >- Captured baseband/LMP framing is the raw material for directed fuzzing of - the BR/EDR Link Manager — crashes, deadlocks and, on some controllers, - code execution — but this control covers only the capture step that + the BR/EDR Link Manager, crashes, deadlocks and, on some controllers, + code execution, but this control covers only the capture step that exposes that framing. preconditions: An original ESP32 with the patched BR/EDR stack and a reachable, authorised target device. summary: >- @@ -51,7 +51,7 @@ attacks: that toolchain. references: - key: garbelini2022esp32sniffer - title: 'esp32_bluetooth_classic_sniffer — Active Bluetooth BR/EDR Sniffer/Injector on the ESP32' + title: 'esp32_bluetooth_classic_sniffer, Active Bluetooth BR/EDR Sniffer/Injector on the ESP32' authors: M. E. Garbelini venue: GitHub (GPL-2.0) year: 2021 @@ -65,14 +65,14 @@ references: url: 'https://www.usenix.org/conference/usenixsecurity22/presentation/garbelini' type: paper - key: braktooth-repo - title: 'braktooth_esp32_bluetooth_classic_attacks — Baseband & LMP exploits against Bluetooth Classic controllers' + title: 'braktooth_esp32_bluetooth_classic_attacks, Baseband & LMP exploits against Bluetooth Classic controllers' authors: M. E. Garbelini venue: GitHub year: 2021 url: 'https://github.com/Matheus-Garbelini/braktooth_esp32_bluetooth_classic_attacks' type: tool - key: ubertooth-rx - title: 'ubertooth-rx(1) — Classic Bluetooth discovery, sniffing, and decoding' + title: 'ubertooth-rx(1), Classic Bluetooth discovery, sniffing, and decoding' authors: Great Scott Gadgets venue: Ubertooth host tools year: 2023 @@ -101,11 +101,11 @@ lastResearched: 2026-06-14 --- ## Mechanism -Bluetooth Classic (BR/EDR) carries data over 79 RF channels of 1 MHz each across 2.402–2.480 GHz, using adaptive frequency hopping at roughly 1600 hops per second; Basic Rate is GFSK at 1 Mbps, while Enhanced Data Rate adds π/4-DQPSK (2 Mbps) and 8DPSK (3 Mbps) (bt-core-spec). This is a different PHY/MAC from BLE — never conflate the two. The fast 79-channel hop is exactly what makes a static software-defined radio impractical as a capture front end: by the time you have demodulated one burst, the piconet is several channels away, so there is no clean per-packet read of a live link from raw I/Q. +Bluetooth Classic (BR/EDR) carries data over 79 RF channels of 1 MHz each across 2.402 to 2.480 GHz, using adaptive frequency hopping at roughly 1600 hops per second; Basic Rate is GFSK at 1 Mbps, while Enhanced Data Rate adds π/4-DQPSK (2 Mbps) and 8DPSK (3 Mbps) (bt-core-spec). This is a different PHY/MAC from BLE, never conflate the two. The fast 79-channel hop is exactly what makes a static software-defined radio impractical as a capture front end: by the time you have demodulated one burst, the piconet is several channels away, so there is no clean per-packet read of a live link from raw I/Q. -The accessible capture path therefore borrows a device that already owns a real Bluetooth controller and exposes the packets the controller has *already* demodulated. The reference approach is the Garbelini ESP32 BR/EDR sniffer: it patches the ESP32's ROM Bluetooth stack so that, after the standard paging procedure, baseband packets — the BT header, channel, device role, FHS, ACL and LMP — are forwarded over USB serial to a host Python tool, `BTSnifferBREDR.py`, which decodes them with Scapy and feeds Wireshark live via an extended `h4bcm` dissector (garbelini2022esp32sniffer). This is an **active** sniffer: it connects itself to the target to follow it, rather than passively listening, so it is for authorised testing only. The same research lineage (Garbelini et al., SUTD/ASSET) built directed Link-Manager fuzzing (BrakTooth) on top of this same baseband-stack patching, which is why a clean capture here is also the first step of the BR/EDR attack surface (garbelini2022braktooth, braktooth-repo). +The accessible capture path therefore borrows a device that already owns a real Bluetooth controller and exposes the packets the controller has *already* demodulated. The reference approach is the Garbelini ESP32 BR/EDR sniffer: it patches the ESP32's ROM Bluetooth stack so that, after the standard paging procedure, baseband packets, the BT header, channel, device role, FHS, ACL and LMP, are forwarded over USB serial to a host Python tool, `BTSnifferBREDR.py`, which decodes them with Scapy and feeds Wireshark live via an extended `h4bcm` dissector (garbelini2022esp32sniffer). This is an **active** sniffer: it connects itself to the target to follow it, rather than passively listening, so it is for authorised testing only. The same research lineage (Garbelini et al., SUTD/ASSET) built directed Link-Manager fuzzing (BrakTooth) on top of this same baseband-stack patching, which is why a clean capture here is also the first step of the BR/EDR attack surface (garbelini2022braktooth, braktooth-repo). -A legacy alternative is the Ubertooth One with `ubertooth-rx`, which can passively pick up *some* Basic-Rate Classic — recovering the LAP/UAP and clock to follow a piconet — but it is partial and lower-fidelity next to the ESP32 baseband sniffer, and it does not see EDR (ubertooth-rx). Either way, the export target is Wireshark for dissection. This control owns only the RF-capture floor: the link-and-above findings (host-stack vulnerabilities, packet injection, replay) are assessed under BSAM once the frames are in a dissector (BSAM-IG-03, BSAM-AP-06). +A legacy alternative is the Ubertooth One with `ubertooth-rx`, which can passively pick up *some* Basic-Rate Classic, recovering the LAP/UAP and clock to follow a piconet, but it is partial and lower-fidelity next to the ESP32 baseband sniffer, and it does not see EDR (ubertooth-rx). Either way, the export target is Wireshark for dissection. This control owns only the RF-capture floor: the link-and-above findings (host-stack vulnerabilities, packet injection, replay) are assessed under BSAM once the frames are in a dissector (BSAM-IG-03, BSAM-AP-06). ## Procedure @@ -143,18 +143,18 @@ A legacy alternative is the Ubertooth One with `ubertooth-rx`, which can passive ## Field case -A sample capture shipped with the Garbelini sniffer (`Matheus-Garbelini/esp32_bluetooth_classic_sniffer`, `logs/samples/ESP32.pcapng`) records exactly this workflow against a BlueKitchen "SPP Counter" btstack demo target running on an ESP32 with BD_ADDR `E0:D4:E8:19:C7:68` — a documented public example of the capture chain end to end, not a live capture of our own (garbelini2022esp32sniffer). To reproduce the same run, an original ESP32-DevKitC running the sniffer pages that BD_ADDR: +A sample capture shipped with the Garbelini sniffer (`Matheus-Garbelini/esp32_bluetooth_classic_sniffer`, `logs/samples/ESP32.pcapng`) records exactly this workflow against a BlueKitchen "SPP Counter" btstack demo target running on an ESP32 with BD_ADDR `E0:D4:E8:19:C7:68`, a documented public example of the capture chain end to end, not a live capture of our own (garbelini2022esp32sniffer). To reproduce the same run, an original ESP32-DevKitC running the sniffer pages that BD_ADDR: ```bash ./BTSnifferBREDR.py --port=/dev/ttyUSB0 --target=E0:D4:E8:19:C7:68 --live-terminal --live-wireshark ``` -In the shipped PCAP the ESP32 pages and follows the link, and the frames include the baseband header, FHS, ACL and LMP that the repo README lists as the sniffer's forwarded packet types; the same BD_ADDR appears little-endian in the capture's FHS frames as the bytes `68 c7 19 e8 d4 e0`, and the target's device-name string reads `SPP Counter E0:D4:E8:19:C7:68` (garbelini2022esp32sniffer). The captured LMP makes the device's pairing and encryption negotiation visible — the raw material the BSAM encryption controls (e.g. minimum key size, force-use-of-encryption) then assess. The same workflow applies unchanged to any authorised Classic target; the btstack SPP demo is simply the concrete, redistributable example the project ships. By contrast, an Ubertooth One on the same target typically returns only intermittent Basic-Rate LAPs and never the LMP, illustrating the wayfinder's note that it is a partial, legacy option for serious BR/EDR work. +In the shipped PCAP the ESP32 pages and follows the link, and the frames include the baseband header, FHS, ACL and LMP that the repo README lists as the sniffer's forwarded packet types; the same BD_ADDR appears little-endian in the capture's FHS frames as the bytes `68 c7 19 e8 d4 e0`, and the target's device-name string reads `SPP Counter E0:D4:E8:19:C7:68` (garbelini2022esp32sniffer). The captured LMP makes the device's pairing and encryption negotiation visible, the raw material the BSAM encryption controls (e.g. minimum key size, force-use-of-encryption) then assess. The same workflow applies unchanged to any authorised Classic target; the btstack SPP demo is simply the concrete, redistributable example the project ships. By contrast, an Ubertooth One on the same target typically returns only intermittent Basic-Rate LAPs and never the LMP, illustrating the wayfinder's note that it is a partial, legacy option for serious BR/EDR work. ## Remediation -Capture feasibility itself is low-criticality — it is the price of using an unlicensed, hopping 2.4 GHz radio, and BR/EDR baseband is observable to anyone with the right controller — so remediation targets what the capture *exposes*, not the capture. +Capture feasibility itself is low-criticality, it is the price of using an unlicensed, hopping 2.4 GHz radio, and BR/EDR baseband is observable to anyone with the right controller, so remediation targets what the capture *exposes*, not the capture. - **Developer / device maker:** do not treat the link as a confidential channel by default. Enforce encryption on every connection (reject unencrypted/role-switched-before-encryption links) and use Secure Simple Pairing with a strong association model; assume LMP and ACL are visible to an attacker with an ESP32. Keep the controller firmware patched against the BrakTooth family, since the same baseband visibility this control uses is the attacker's fuzzing entry point (garbelini2022braktooth). - **Integrator:** prefer dual-mode/LE where the threat model allows, pin firmware to versions with current BR/EDR controller patches, and disable discoverability and unused profiles to shrink what a follower can reach. -- **Operator / assessor:** run active BR/EDR capture only under authorisation and ideally in an RF-shielded environment; treat the resulting PCAP as input to the BSAM host-stack and injection/replay controls (BSAM-IG-03, BSAM-AP-06) rather than a finding in itself. Frame any CVE corpus (BrakTooth and successors) as representative — check current vendor advisories, as BR/EDR controller patch status moves. +- **Operator / assessor:** run active BR/EDR capture only under authorisation and ideally in an RF-shielded environment; treat the resulting PCAP as input to the BSAM host-stack and injection/replay controls (BSAM-IG-03, BSAM-AP-06) rather than a finding in itself. Frame any CVE corpus (BrakTooth and successors) as representative, check current vendor advisories, as BR/EDR controller patch status moves. diff --git a/src/content/controls/rfsam-btc-sp-01.md b/src/content/controls/rfsam-btc-sp-01.md index f71cc93..35368f1 100644 --- a/src/content/controls/rfsam-btc-sp-01.md +++ b/src/content/controls/rfsam-btc-sp-01.md @@ -9,24 +9,24 @@ applicability: deferred: false objective: >- Confirm a Bluetooth Classic (BR/EDR) device is present and reachable, and - enumerate the discoverable devices in range — BD_ADDR, name, RSSI and Class of - Device — corroborating that activity with an SDR waterfall over the 2.4 GHz + enumerate the discoverable devices in range, BD_ADDR, name, RSSI and Class of + Device, corroborating that activity with an SDR waterfall over the 2.4 GHz band. intro: >- The "see it" floor for Bluetooth Classic. An inquiry scan on a cheap ESP32 lists every discoverable BR/EDR device's BD_ADDR, name, RSSI and Class of - Device — the BR/EDR analogue of a BLE advertising scan — while an SDR waterfall + Device, the BR/EDR analogue of a BLE advertising scan, while an SDR waterfall confirms the band is busy. Be honest about the ceiling: ~1600 hops/s adaptive frequency hopping means the SDR shows activity, not a clean per-packet read, and the inquiry scan only finds devices currently in discoverable mode. prerequisites: hardware: - - 'An original ESP32 (BR/EDR-capable radio) DevKit — an ESP32-S3/C-series has no Bluetooth Classic radio and cannot run an inquiry scan' - - 'Optional: a wideband SDR for the waterfall — HackRF One or bladeRF 2.0 micro' + - 'An original ESP32 (BR/EDR-capable radio) DevKit, an ESP32-S3/C-series has no Bluetooth Classic radio and cannot run an inquiry scan' + - 'Optional: a wideband SDR for the waterfall, HackRF One or bladeRF 2.0 micro' software: - 'ClassicBTScan or ESP32-BT-exp (Arduino-ESP32, Bluedroid GAP inquiry); Gqrx for the SDR waterfall' signal: - freq: '2.402–2.480 GHz (79 RF channels × 1 MHz, adaptive frequency hopping ~1600 hops/s)' + freq: '2.402 to 2.480 GHz (79 RF channels × 1 MHz, adaptive frequency hopping ~1600 hops/s)' bandwidth: '1 MHz per RF channel' modulation: 'GFSK 1 Mbps (Basic Rate); π/4-DQPSK 2 Mbps & 8DPSK 3 Mbps (EDR)' skill: beginner @@ -39,27 +39,27 @@ attacks: - armis-blueborne impact: >- Leaks bytes of controller/host memory over the SDP service-discovery - response — no pairing, authentication or user interaction — which the + response, no pairing, authentication or user interaction, which the BlueBorne chain then uses to defeat ASLR ahead of a remote code-execution step. preconditions: >- The device is reachable on BR/EDR and answers service-discovery requests; a discoverable device found by this inquiry scan is exactly such a target. - Patched on maintained stacks since 2017 — representative of the class, not + Patched on maintained stacks since 2017, representative of the class, not a current finding. summary: >- Shows why "merely reachable and discoverable" is itself a finding at the spectrum layer: an unauthenticated SDP query against a reachable BR/EDR device can disclose memory, the entry point of the BlueBorne attack vector. - - name: BrakTooth (baseband/LMP — downstream) + - name: BrakTooth (baseband/LMP, downstream) refs: - garbelini-braktooth impact: >- Crash, deadlock or (on some controllers) code execution against the BR/EDR - baseband/Link Manager — but this is an AT-layer follow-on; this control only + baseband/Link Manager, but this is an AT-layer follow-on; this control only establishes the reachability precondition it needs. preconditions: >- - A reachable BR/EDR controller whose BD_ADDR is known — which is precisely + A reachable BR/EDR controller whose BD_ADDR is known, which is precisely what an inquiry scan yields. Treat the affected-chip list as representative; check current vendor advisories. summary: >- @@ -69,13 +69,13 @@ attacks: performs. references: - key: bt-baseband-spec - title: 'Bluetooth Core Specification — Part B, Baseband Specification (inquiry procedure, BD_ADDR, inquiry access codes)' + title: 'Bluetooth Core Specification, Part B, Baseband Specification (inquiry procedure, BD_ADDR, inquiry access codes)' authors: Bluetooth SIG venue: Bluetooth SIG Core Specification url: 'https://www.bluetooth.com/wp-content/uploads/Files/Specification/HTML/Core-54/out/en/br-edr-controller/baseband-specification.html' type: spec - key: bt-gap-spec - title: 'Bluetooth Core Specification — Part C, Generic Access Profile (Class of Device, BR/EDR discoverability and inquiry procedures)' + title: 'Bluetooth Core Specification, Part C, Generic Access Profile (Class of Device, BR/EDR discoverability and inquiry procedures)' authors: Bluetooth SIG venue: Bluetooth SIG Core Specification url: 'https://www.bluetooth.com/wp-content/uploads/Files/Specification/HTML/Core-54/out/en/host/generic-access-profile.html' @@ -87,7 +87,7 @@ references: url: 'https://nvd.nist.gov/vuln/detail/CVE-2017-0785' type: cve - key: armis-blueborne - title: 'BlueBorne — Bluetooth attack vector (technical white paper)' + title: 'BlueBorne, Bluetooth attack vector (technical white paper)' authors: Armis venue: Armis Labs year: 2017 @@ -101,7 +101,7 @@ references: url: 'https://github.com/Matheus-Garbelini/braktooth_esp32_bluetooth_classic_attacks' type: tool - key: antorfr-classicbtscan - title: 'ClassicBTScan — Arduino-ESP32 Bluetooth Classic (BR/EDR) inquiry scanner' + title: 'ClassicBTScan, Arduino-ESP32 Bluetooth Classic (BR/EDR) inquiry scanner' authors: AntorFr venue: GitHub url: 'https://github.com/AntorFr/ClassicBTScan' @@ -122,24 +122,24 @@ lastResearched: 2026-06-14 Bluetooth Classic (BR/EDR) is a different PHY/MAC from BLE: it occupies the same 2.4 GHz ISM band but uses 79 RF channels of 1 MHz each and hops across them under adaptive frequency hopping (AFH) at roughly 1600 hops per second (bt-baseband-spec). That fast hop is exactly why the spectrum layer for Classic splits into two complementary moves rather than one. -The first move is a **spectrum view**. A waterfall over 2.402–2.480 GHz shows BR/EDR bursts scattered across the band, confirming that "something Bluetooth is busy here" — but you cannot lock to one channel and follow a piconet packet-by-packet the way you can with a fixed-channel protocol. At 1600 hops/s a static SDR simply cannot keep up, so the waterfall is an *activity* indicator, not a decode. This is the honest ceiling of SDR at this layer. +The first move is a **spectrum view**. A waterfall over 2.402 to 2.480 GHz shows BR/EDR bursts scattered across the band, confirming that "something Bluetooth is busy here", but you cannot lock to one channel and follow a piconet packet-by-packet the way you can with a fixed-channel protocol. At 1600 hops/s a static SDR simply cannot keep up, so the waterfall is an *activity* indicator, not a decode. This is the honest ceiling of SDR at this layer. -The second, and usually more useful, move is an **inquiry scan**. A discoverable BR/EDR device parks in inquiry-scan mode and answers the general inquiry access code (GIAC, LAP 0x9E8B33) with an FHS packet carrying its 48-bit BD_ADDR and its Class of Device, and — after a name request — its user-facing name (bt-baseband-spec, bt-gap-spec). Cheap ESP32 firmware runs a *real* BR/EDR inquiry on the chip's own Bluetooth controller via the Bluedroid GAP API and lists each discoverable device's BD_ADDR, name, RSSI and Class of Device (antorfr-classicbtscan) — the BR/EDR analogue of a BLE advertising scan, and the most practical "see it" step for Classic. Two limits are intrinsic: it only finds devices currently in discoverable mode (a non-discoverable device must be addressed by a BD_ADDR you already know), and Classic inquiry needs the original ESP32 — an S3/C-series part has no BR/EDR radio. +The second, and usually more useful, move is an **inquiry scan**. A discoverable BR/EDR device parks in inquiry-scan mode and answers the general inquiry access code (GIAC, LAP 0x9E8B33) with an FHS packet carrying its 48-bit BD_ADDR and its Class of Device, and, after a name request, its user-facing name (bt-baseband-spec, bt-gap-spec). Cheap ESP32 firmware runs a *real* BR/EDR inquiry on the chip's own Bluetooth controller via the Bluedroid GAP API and lists each discoverable device's BD_ADDR, name, RSSI and Class of Device (antorfr-classicbtscan), the BR/EDR analogue of a BLE advertising scan, and the most practical "see it" step for Classic. Two limits are intrinsic: it only finds devices currently in discoverable mode (a non-discoverable device must be addressed by a BD_ADDR you already know), and Classic inquiry needs the original ESP32, an S3/C-series part has no BR/EDR radio. -Why this is a finding and not just reconnaissance: a device that is *reachable and discoverable* is, by itself, the precondition for the rest of the Classic attack surface. BlueBorne's SDP information-disclosure flaw (CVE-2017-0785) leaks memory from a reachable BR/EDR device with no pairing, authentication or user interaction at all (cve-2017-0785, armis-blueborne); the BrakTooth baseband/LMP suite needs only a reachable controller and its BD_ADDR to fire (garbelini-braktooth). Both are downstream of this control — listed to make the SP→CR/AT descent explicit — but they are the reason "I can see it and it answers" matters. Treat both CVE corpora as representative and patch-dependent; check current advisories. +Why this is a finding and not just reconnaissance: a device that is *reachable and discoverable* is, by itself, the precondition for the rest of the Classic attack surface. BlueBorne's SDP information-disclosure flaw (CVE-2017-0785) leaks memory from a reachable BR/EDR device with no pairing, authentication or user interaction at all (cve-2017-0785, armis-blueborne); the BrakTooth baseband/LMP suite needs only a reachable controller and its BD_ADDR to fire (garbelini-braktooth). Both are downstream of this control, listed to make the SP→CR/AT descent explicit, but they are the reason "I can see it and it answers" matters. Treat both CVE corpora as representative and patch-dependent; check current advisories. ## Procedure -> Authorised testing only — run this against devices you own or are explicitly contracted to assess. An inquiry scan is passive at the application layer but still transmits inquiry packets in a licensed-free band; the SDR waterfall is receive-only. +> Authorised testing only, run this against devices you own or are explicitly contracted to assess. An inquiry scan is passive at the application layer but still transmits inquiry packets in a licensed-free band; the SDR waterfall is receive-only. 1. **Confirm band activity with the SDR waterfall (receive-only).** Bring up Gqrx on a HackRF One or bladeRF 2.0 micro, tune to the centre of the band and watch for hopping bursts: ```bash - # HackRF: 2.441 GHz centre, 20 Msps, covers most of the 2.402–2.480 GHz band + # HackRF: 2.441 GHz centre, 20 Msps, covers most of the 2.402 to 2.480 GHz band gqrx # Device string: hackrf=0 (or bladerf=0) # Set frequency 2.441 GHz, sample rate 20 Msps, enable the waterfall ``` - You should see short bursts skipping unpredictably across the span. That is BR/EDR (and BLE/Wi-Fi) activity — it confirms the band is busy, but you cannot follow one piconet here. Do not expect a clean per-packet decode (garbelini-braktooth, bt-baseband-spec). + You should see short bursts skipping unpredictably across the span. That is BR/EDR (and BLE/Wi-Fi) activity, it confirms the band is busy, but you cannot follow one piconet here. Do not expect a clean per-packet decode (garbelini-braktooth, bt-baseband-spec). 2. **Run a BR/EDR inquiry scan on the original ESP32.** Flash ClassicBTScan (or ESP32-BT-exp for a dual-mode Classic+BLE dump) to an original ESP32 DevKit and open the serial monitor at 115200 baud: ```bash @@ -149,18 +149,18 @@ Why this is a finding and not just reconnaissance: a device that is *reachable a arduino-cli monitor -p /dev/ttyUSB0 -c baudrate=115200 ``` The sketch calls the Bluedroid GAP inquiry API and prints one line per discoverable device. Read each field: - - **BD_ADDR** — 48-bit address; the upper 24 bits are the OUI (vendor lookup). - - **Name** — the user-facing name from the name request (may be empty). - - **RSSI** — coarse proximity / link-budget indicator. - - **Class of Device (CoD)** — the device-type hint (audio, peripheral/HID, phone, etc.). + - **BD_ADDR**, 48-bit address; the upper 24 bits are the OUI (vendor lookup). + - **Name**, the user-facing name from the name request (may be empty). + - **RSSI**, coarse proximity / link-budget indicator. + - **Class of Device (CoD)**, the device-type hint (audio, peripheral/HID, phone, etc.). -3. **Record the inventory and cross-reference.** For each hit, note BD_ADDR, name, RSSI and CoD, and resolve the OUI to a vendor. Devices in this list are *reachable and discoverable* — flag that as the spectrum-layer finding, and carry the BD_ADDRs forward to the IG fingerprinting and the CR/AT layers. +3. **Record the inventory and cross-reference.** For each hit, note BD_ADDR, name, RSSI and CoD, and resolve the OUI to a vendor. Devices in this list are *reachable and discoverable*, flag that as the spectrum-layer finding, and carry the BD_ADDRs forward to the IG fingerprinting and the CR/AT layers. -4. **Note what you did not see.** A device that is paired-and-connected but non-discoverable will not appear. Absence from the inquiry list is not proof of absence on the air — corroborate with the step-1 waterfall (band busy but no inquiry hits ⇒ likely non-discoverable / already-bonded traffic). See RFSAM-RES-26 for the ESP32 inquiry-scanning walkthrough. +4. **Note what you did not see.** A device that is paired-and-connected but non-discoverable will not appear. Absence from the inquiry list is not proof of absence on the air, corroborate with the step-1 waterfall (band busy but no inquiry hits ⇒ likely non-discoverable / already-bonded traffic). See RFSAM-RES-26 for the ESP32 inquiry-scanning walkthrough. ## Field case -Assessing a hands-free car kit and its paired peripherals on the bench, the SDR waterfall over 2.402–2.480 GHz showed steady hopping bursts the moment the head unit powered on — band confirmed busy, but, as expected, nothing followable at ~1600 hops/s. The ESP32 inquiry scan then returned a short inventory: +Assessing a hands-free car kit and its paired peripherals on the bench, the SDR waterfall over 2.402 to 2.480 GHz showed steady hopping bursts the moment the head unit powered on, band confirmed busy, but, as expected, nothing followable at ~1600 hops/s. The ESP32 inquiry scan then returned a short inventory: ``` [BR/EDR inquiry] @@ -168,12 +168,12 @@ Assessing a hands-free car kit and its paired peripherals on the bench, the SDR BD_ADDR=[FILL: 48-bit address] name="[FILL: HID name]" RSSI=-71 CoD=0x002540 (Peripheral, keyboard) ``` -The CoD `0x240404` cleanly identified the hands-free audio unit, and its OUI [FILL: vendor from upper 24 bits] matched the expected infotainment vendor. The keyboard peripheral was discoverable too — an avoidable exposure, since an HID device only needs to be discoverable during pairing. The takeaway recorded at this layer was simply: two reachable, discoverable BR/EDR devices, BD_ADDRs captured, both now in scope for the IG/CR/AT descent. The bracketed `[FILL: …]` values above are illustrative placeholders, not a real capture — replace them with the actual inquiry output from your authorised engagement rather than treating them as findings. +The CoD `0x240404` cleanly identified the hands-free audio unit, and its OUI [FILL: vendor from upper 24 bits] matched the expected infotainment vendor. The keyboard peripheral was discoverable too, an avoidable exposure, since an HID device only needs to be discoverable during pairing. The takeaway recorded at this layer was simply: two reachable, discoverable BR/EDR devices, BD_ADDRs captured, both now in scope for the IG/CR/AT descent. The bracketed `[FILL: …]` values above are illustrative placeholders, not a real capture, replace them with the actual inquiry output from your authorised engagement rather than treating them as findings. ## Remediation -**Developer / firmware.** Do not leave a device in general-discoverable (inquiry-scan) mode after provisioning. Make discoverability a time-boxed, user-initiated pairing window (limited-discoverable, then back to non-discoverable), so a passing inquiry scan returns nothing. Set the Class of Device honestly but minimally — it is a routing hint, not a place for extra detail. Keep the BR/EDR controller and host stack patched against the known reachable-surface classes (BlueBorne SDP leak and the BrakTooth baseband/LMP family); treat those CVE lists as representative and re-check current vendor advisories (cve-2017-0785, garbelini-braktooth). +**Developer / firmware.** Do not leave a device in general-discoverable (inquiry-scan) mode after provisioning. Make discoverability a time-boxed, user-initiated pairing window (limited-discoverable, then back to non-discoverable), so a passing inquiry scan returns nothing. Set the Class of Device honestly but minimally, it is a routing hint, not a place for extra detail. Keep the BR/EDR controller and host stack patched against the known reachable-surface classes (BlueBorne SDP leak and the BrakTooth baseband/LMP family); treat those CVE lists as representative and re-check current vendor advisories (cve-2017-0785, garbelini-braktooth). -**Integrator.** Prefer modules that ship non-discoverable by default and expose discoverability only behind an explicit user action. Where a generic device name leaks model/vendor, override it. These link-and-above concerns are owned by BSAM's Bluetooth controls — RFSAM stops at confirming reachability and capturing the inventory, and defers the controller lifecycle/patch assessment to BSAM (BSAM-IG-01). +**Integrator.** Prefer modules that ship non-discoverable by default and expose discoverability only behind an explicit user action. Where a generic device name leaks model/vendor, override it. These link-and-above concerns are owned by BSAM's Bluetooth controls, RFSAM stops at confirming reachability and capturing the inventory, and defers the controller lifecycle/patch assessment to BSAM (BSAM-IG-01). **Operator.** Power devices down or disable Bluetooth when not in use; pair in a trusted location and within the shortest possible discoverable window. Periodically run an inquiry scan of your own estate to find devices that are needlessly discoverable. A device that never answers an inquiry scan denies an attacker the cheapest reconnaissance step in the entire Classic descent. diff --git a/src/content/controls/rfsam-gnss-at-01.md b/src/content/controls/rfsam-gnss-at-01.md index bd518f8..2c31398 100644 --- a/src/content/controls/rfsam-gnss-at-01.md +++ b/src/content/controls/rfsam-gnss-at-01.md @@ -14,7 +14,7 @@ deferred: false objective: >- Determine whether a GNSS receiver can be made to report an attacker-chosen position or time by a counterfeit (spoofed) civilian signal, or be denied any - fix by in-band jamming — and whether it detects, alarms on, or rejects either + fix by in-band jamming, and whether it detects, alarms on, or rejects either condition. Authorised, RF-contained testing only. intro: >- Civilian GNSS signals (GPS L1 C/A, GLONASS, BeiDou B1, Galileo E1 OS) are @@ -27,7 +27,7 @@ prerequisites: hardware: - 'A TX-capable SDR: HackRF One, bladeRF 2.0 micro, or USRP B210 (RTL-SDR is receive-only and cannot transmit)' - 'The target GNSS receiver (module, handset, or timing reference) under test' - - 'RF containment: a shielded enclosure or a cabled (conducted) path with attenuators — over-the-air GNSS TX is illegal in most jurisdictions' + - 'RF containment: a shielded enclosure or a cabled (conducted) path with attenuators, over-the-air GNSS TX is illegal in most jurisdictions' - 'Optionally a reference GNSS receiver (e.g. u-blox NEO) to observe satellite count and C/N0 during the test' software: - 'gps-sdr-sim (signal synthesis for the spoofing case)' @@ -46,7 +46,7 @@ attacks: - utexas2013yacht impact: >- Receiver locks onto the counterfeit signal and reports an attacker-chosen - position and/or clock, with no alarm — downstream navigation, geofencing, + position and/or clock, with no alarm, downstream navigation, geofencing, timestamping or PPS timing follows the false fix. preconditions: >- A receiver tracking unauthenticated civilian signals; the spoofer must @@ -85,7 +85,7 @@ references: url: 'https://doi.org/10.1109/JPROC.2016.2526658' type: paper - key: texbat - title: 'TEXBAT — Texas Spoofing Test Battery (civil GPS L1 C/A spoofing recordings)' + title: 'TEXBAT, Texas Spoofing Test Battery (civil GPS L1 C/A spoofing recordings)' authors: 'T. E. Humphreys, J. A. Bhatti, D. P. Shepard, K. D. Wesson (UT Austin Radionavigation Laboratory)' venue: UT Austin Radionavigation Laboratory year: 2012 @@ -106,7 +106,7 @@ references: url: 'https://www.gsc-europa.eu/sites/default/files/sites/all/files/Galileo_OSNMA_SIS_ICD_v1.1.pdf' type: standard - key: gps-sdr-sim - title: 'gps-sdr-sim — Software-Defined GPS Signal Simulator' + title: 'gps-sdr-sim, Software-Defined GPS Signal Simulator' authors: T. Ebinuma (osqzss) venue: GitHub year: 2024 @@ -129,13 +129,13 @@ lastResearched: 2026-06-14 --- ## Mechanism -A civilian GNSS receiver derives position and time entirely from signals it cannot authenticate. GPS L1 C/A is BPSK on a 1575.42 MHz carrier, spread by a public 1023-chip code at 1.023 Mcps repeating every 1 ms, carrying a 50 bps navigation message; the same applies to GLONASS, BeiDou B1 and Galileo E1 OS — the codes and message format are published, so any receiver decodes them and, equally, anyone can generate them [galileo-osnma]. The recovered signal sits roughly 30 dB below the noise floor and is pulled out only by correlating against the known code, which is exactly why a marginally stronger counterfeit can win the correlation and capture the receiver [psiaki2016survey]. +A civilian GNSS receiver derives position and time entirely from signals it cannot authenticate. GPS L1 C/A is BPSK on a 1575.42 MHz carrier, spread by a public 1023-chip code at 1.023 Mcps repeating every 1 ms, carrying a 50 bps navigation message; the same applies to GLONASS, BeiDou B1 and Galileo E1 OS, the codes and message format are published, so any receiver decodes them and, equally, anyone can generate them [galileo-osnma]. The recovered signal sits roughly 30 dB below the noise floor and is pulled out only by correlating against the known code, which is exactly why a marginally stronger counterfeit can win the correlation and capture the receiver [psiaki2016survey]. -Two attack families exploit this. **Spoofing** synthesises a valid-looking signal and transmits it at higher power than the live sky; once the receiver locks onto it, the attacker can drag the reported position or clock to chosen values. A portable software-defined civilian spoofer was first built and characterised by Humphreys et al., who showed a commodity receiver could be captured and walked away from truth without raising any alarm [humphreys2008spoof]. The technique was later demonstrated against a moving target — a superyacht at sea — where counterfeit signals slowly overpowered the authentic ones and steered the vessel's navigation off course while its display still showed a straight line [utexas2013yacht]. The Texas Spoofing Test Battery (TEXBAT) standardised a set of recorded L1 C/A spoofing scenarios (static and dynamic, with matched clean recordings) so that receiver/detector resilience can be evaluated against a common reference [texbat]. +Two attack families exploit this. **Spoofing** synthesises a valid-looking signal and transmits it at higher power than the live sky; once the receiver locks onto it, the attacker can drag the reported position or clock to chosen values. A portable software-defined civilian spoofer was first built and characterised by Humphreys et al., who showed a commodity receiver could be captured and walked away from truth without raising any alarm [humphreys2008spoof]. The technique was later demonstrated against a moving target, a superyacht at sea, where counterfeit signals slowly overpowered the authentic ones and steered the vessel's navigation off course while its display still showed a straight line [utexas2013yacht]. The Texas Spoofing Test Battery (TEXBAT) standardised a set of recorded L1 C/A spoofing scenarios (static and dynamic, with matched clean recordings) so that receiver/detector resilience can be evaluated against a common reference [texbat]. **Jamming** is the blunt counterpart: raising the in-band noise or interference floor over the target band above the receiver's despreading margin denies any fix at all. Because the legitimate signal is so weak, modest in-band power is enough to deny it; the resilience question is whether the receiver flags the loss of integrity or silently coasts and accepts the first plausible fix it reacquires [psiaki2016survey]. -The defensive state of the art splits into cryptographic and non-cryptographic checks. Galileo OSNMA adds optional navigation-message authentication on E1-B using a TESLA-style scheme (digitally signing the Open Service I/NAV message), letting an OSNMA-aware receiver verify the message originated from the system; EUSPA declared the OSNMA Initial Service operational on 24 July 2025 [galileo-osnma]. Crediting a target with message-authentication resilience requires confirming the specific receiver under test actually validates OSNMA, not merely that the constellation broadcasts it. Receivers can also apply non-cryptographic consistency checks — power/distortion monitoring, RAIM, clock-jump and inertial cross-checks, angle-of-arrival with multiple antennas — surveyed in [psiaki2016survey]. Legacy GPS L1 C/A on its own offers none of these, which is what this control tests for. +The defensive state of the art splits into cryptographic and non-cryptographic checks. Galileo OSNMA adds optional navigation-message authentication on E1-B using a TESLA-style scheme (digitally signing the Open Service I/NAV message), letting an OSNMA-aware receiver verify the message originated from the system; EUSPA declared the OSNMA Initial Service operational on 24 July 2025 [galileo-osnma]. Crediting a target with message-authentication resilience requires confirming the specific receiver under test actually validates OSNMA, not merely that the constellation broadcasts it. Receivers can also apply non-cryptographic consistency checks, power/distortion monitoring, RAIM, clock-jump and inertial cross-checks, angle-of-arrival with multiple antennas, surveyed in [psiaki2016survey]. Legacy GPS L1 C/A on its own offers none of these, which is what this control tests for. ## Procedure @@ -145,37 +145,37 @@ All transmit steps are **authorised, RF-contained testing only**: your own equip ```bash gpsmon /dev/ttyACM0 ``` - Expected: GGA/RMC sentences with a valid 3D fix, GSV showing several satellites at healthy C/N0 (typically 35–50 dB-Hz). Record the true position and fix quality. + Expected: GGA/RMC sentences with a valid 3D fix, GSV showing several satellites at healthy C/N0 (typically 35 to 50 dB-Hz). Record the true position and fix quality. -2. Jamming resilience — monitor the band. In the contained setup, tune gqrx to L1 and confirm a clean baseline, then introduce the jamming source (a TX-capable SDR driving a carrier or noise over L1) and watch the band fill. +2. Jamming resilience, monitor the band. In the contained setup, tune gqrx to L1 and confirm a clean baseline, then introduce the jamming source (a TX-capable SDR driving a carrier or noise over L1) and watch the band fill. ```bash gqrx # tune to 1575.42 MHz, observe the waterfall ``` Expected: baseline shows a quiet band (the GNSS signal itself is below the noise floor and not visible); during jamming a strong carrier or wideband hump appears over L1. gqrx observes only; it does not transmit. -3. Jamming resilience — observe the target. With the jammer active, watch the target receiver. +3. Jamming resilience, observe the target. With the jammer active, watch the target receiver. ```bash cgps -s ``` - Expected: satellite count drops, C/N0 collapses, the fix is lost. Record whether the receiver raises an integrity/loss alarm, coasts on its last fix, or silently goes stale — and how long it takes to reacquire after the jammer stops. + Expected: satellite count drops, C/N0 collapses, the fix is lost. Record whether the receiver raises an integrity/loss alarm, coasts on its last fix, or silently goes stale, and how long it takes to reacquire after the jammer stops. -4. Spoofing — synthesise the counterfeit signal. Fetch a current RINEX broadcast ephemeris (`brdc` file) and generate an L1 C/A baseband for a chosen static position. The `-b 8` option emits 8-bit signed I/Q for HackRF. +4. Spoofing, synthesise the counterfeit signal. Fetch a current RINEX broadcast ephemeris (`brdc` file) and generate an L1 C/A baseband for a chosen static position. The `-b 8` option emits 8-bit signed I/Q for HackRF. ```bash gps-sdr-sim -e brdc0010.22n -l 30.286502,120.032669,100 -b 8 ``` Expected: a `gpssim.bin` baseband file for the chosen latitude,longitude,height. Use the matching sample rate/format for your radio (HackRF/bladeRF accept the 2.6 MHz default; USRP requires 2.5 MHz). A moving track can be supplied instead with `-u`/`-x`/`-g`. -5. Spoofing — transmit into the contained setup (authorised only). For HackRF the file must be 8-bit signed I/Q: +5. Spoofing, transmit into the contained setup (authorised only). For HackRF the file must be 8-bit signed I/Q: ```bash hackrf_transfer -t gpssim.bin -f 1575420000 -s 2600000 -a 1 -x 0 ``` Expected: the synthesised signal is radiated into the shielded/cabled path. Start at low gain and raise it until the target prefers the counterfeit. (bladeRF replays via `bladeRF-cli`; USRP via `gps-sdr-sim-uhd.py` or `tx_samples_from_file --freq 1575420000`.) -6. Spoofing — confirm capture. Watch the target output while the counterfeit is live. +6. Spoofing, confirm capture. Watch the target output while the counterfeit is live. ```bash cgps -s ``` - Expected: a resilient receiver rejects the spoof, flags an integrity fault, or refuses to move; a vulnerable one walks its reported position toward the synthesised coordinates (`30.286502,120.032669` in the example) and/or steps its clock — with no alarm. Record the transition and whether any anti-spoof flag was raised. + Expected: a resilient receiver rejects the spoof, flags an integrity fault, or refuses to move; a vulnerable one walks its reported position toward the synthesised coordinates (`30.286502,120.032669` in the example) and/or steps its clock, with no alarm. Record the transition and whether any anti-spoof flag was raised. 7. Reproducible offline variant. Where transmitting is not permitted at all, validate detector behaviour against the recorded TEXBAT scenarios (each spoofed set has a matched clean recording) by feeding them to a software receiver rather than radiating [texbat]. @@ -195,14 +195,14 @@ and replayed into the enclosure with hackrf_transfer -t gpssim.bin -f 1575420000 -s 2600000 -a 1 -x 0 ``` -raising `-a`/gain stepwise. Observed outcome: [FILL: at what relative power / after how many seconds] the module's reported position migrates from its true location toward `30.286502, 120.032669` and the fix follows the decoy, with [FILL: alarm raised? yes/no — record any integrity/anti-spoof flag]. Jamming run: a carrier at 1575.42 MHz is introduced; the module loses lock and [FILL: coasts / alarms / goes stale — record behaviour] and reacquires after [FILL: measured reacquisition time] once removed. +raising `-a`/gain stepwise. Observed outcome: [FILL: at what relative power / after how many seconds] the module's reported position migrates from its true location toward `30.286502, 120.032669` and the fix follows the decoy, with [FILL: alarm raised? yes/no, record any integrity/anti-spoof flag]. Jamming run: a carrier at 1575.42 MHz is introduced; the module loses lock and [FILL: coasts / alarms / goes stale, record behaviour] and reacquires after [FILL: measured reacquisition time] once removed. -This mirrors the public demonstrations — a portable spoofer capturing a commodity receiver [humphreys2008spoof] and the same class of attack steering a superyacht's navigation while its display showed no anomaly [utexas2013yacht] — at bench scale and under RF containment. No first-party measurements were taken for this control: every `[FILL: …]` marker (satellite count, C/N0, capture power/time, alarm behaviour, reacquisition time) is an unmeasured placeholder for the operator to complete from an actual contained run on their own hardware. They are method scaffolding, not asserted findings. +This mirrors the public demonstrations, a portable spoofer capturing a commodity receiver [humphreys2008spoof] and the same class of attack steering a superyacht's navigation while its display showed no anomaly [utexas2013yacht], at bench scale and under RF containment. No first-party measurements were taken for this control: every `[FILL: …]` marker (satellite count, C/N0, capture power/time, alarm behaviour, reacquisition time) is an unmeasured placeholder for the operator to complete from an actual contained run on their own hardware. They are method scaffolding, not asserted findings. ## Remediation Layered, because no single check is sufficient against both spoofing and jamming [psiaki2016survey]: - **Developer (receiver/firmware).** Implement consistency checks that legacy C/A omits: power/distortion (C/N0 and correlation-peak) monitoring, RAIM/integrity across satellites, clock-jump and position-jump sanity limits, and rejection of physically impossible velocity/altitude. Where the chipset supports it, enable Galileo OSNMA so the navigation message is cryptographically authenticated and a counterfeit E1 message is detected [galileo-osnma]. Validate the implementation against a standard spoofing test set such as TEXBAT [texbat]. -- **Integrator (device/system).** Cross-check GNSS-derived position and time against independent sources — inertial navigation, wheel/odometry, a holdover oscillator for timing, multi-antenna angle-of-arrival, or a second constellation/band. Make loss of GNSS integrity an explicit, alarmed state rather than a silent coast; do not let the system accept the first plausible reacquired fix without re-validation. +- **Integrator (device/system).** Cross-check GNSS-derived position and time against independent sources, inertial navigation, wheel/odometry, a holdover oscillator for timing, multi-antenna angle-of-arrival, or a second constellation/band. Make loss of GNSS integrity an explicit, alarmed state rather than a silent coast; do not let the system accept the first plausible reacquired fix without re-validation. - **Operator.** Treat continuous, unmonitored GNSS as untrusted for safety- or security-critical decisions. Monitor for jamming/interference (a sustained L1 carrier or noise floor is the tell), define a degraded-mode procedure for loss of fix, and prefer authenticated or multi-constellation/multi-band receivers where the application warrants it. Conduct any spoofing/jamming testing only under authorisation and RF containment. diff --git a/src/content/controls/rfsam-gnss-sp-01.md b/src/content/controls/rfsam-gnss-sp-01.md index 444bc31..495b55d 100644 --- a/src/content/controls/rfsam-gnss-sp-01.md +++ b/src/content/controls/rfsam-gnss-sp-01.md @@ -13,13 +13,13 @@ applicability: deferred: false objective: >- Confirm that the GNSS L-band is usable at the test site and detect any - interference or jamming that would degrade or deny a receiver's fix — judged + interference or jamming that would degrade or deny a receiver's fix, judged from the RF environment (waterfall) and the receiver's own carrier-to-noise (C/N0) and satellite-count reports, not from the GNSS signal itself, which sits below the noise floor. intro: >- GNSS signals arrive far below the thermal noise floor, so on a spectrum - waterfall you are not looking for the signal — you are looking for what is + waterfall you are not looking for the signal, you are looking for what is wrong on top of it. This control confirms the band is healthy and surveys for the interference and jamming that deny civilian receivers their fix. It is the RF-environment baseline that every later GNSS step (decode, spoof-resilience) @@ -35,7 +35,7 @@ prerequisites: - 'optional: gnss-sdr for a software-receiver C/N0 reading from the same I/Q' signal: freq: 'L1 1575.42 MHz (GPS L1 C/A · Galileo E1 OS overlap). Neighbours: GLONASS L1 ~1602 MHz, BeiDou B1 1561.098 MHz; wider band L2 1227.60 MHz, L5 1176.45 MHz' - bandwidth: '~2 MHz null-to-null for the C/A main lobe (1.023 Mcps spreading); survey ~2.5–20 MHz around L1' + bandwidth: '~2 MHz null-to-null for the C/A main lobe (1.023 Mcps spreading); survey ~2.5 to 20 MHz around L1' modulation: 'BPSK on the carrier; 1023-chip C/A code at 1.023 Mcps repeating every 1 ms; received power about -128.5 dBm (-158.5 dBW), below the noise floor' skill: intermediate attacks: @@ -45,7 +45,7 @@ attacks: - easa2025gnss impact: >- Floods L1 with noise or a carrier so the receiver cannot despread any - satellite — C/N0 collapses and the fix is lost, denying navigation, + satellite, C/N0 collapses and the fix is lost, denying navigation, geofencing or a timing/PPS reference downstream. preconditions: >- A transmitter on or near L1 within range; trivial because civilian GNSS is @@ -61,7 +61,7 @@ attacks: impact: >- A spoofer transmits a valid-looking, slightly stronger L1 C/A signal to capture the receiver and drag its position/time; its onset can present as - a C/N0 that is implausibly high for the elevated received power — an + a C/N0 that is implausibly high for the elevated received power, an abnormal imbalance between C/N0 and power. preconditions: >- A counterfeit L1 signal stronger than the live sky at the receiver. This @@ -122,11 +122,11 @@ lastResearched: 2026-06-14 ## Mechanism -A GPS L1 C/A signal is BPSK on a 1575.42 MHz carrier, spread by a 1023-chip code at 1.023 Mcps that repeats every 1 ms, with one PRN code per satellite (CDMA). It arrives extremely weak: the GPS SPS Performance Standard guarantees a received signal power of only **-158.5 dBW (-128.5 dBm) for the L1 C/A-code** under the IS-GPS-200 reference conditions, which is below the thermal noise floor — the signal is recovered only by correlating against the known PRN code [spsps2020]. The practical consequence for an SP-layer survey is decisive: **you cannot see the GNSS signal on a waterfall.** A clean, quiet band at L1 *is* the healthy picture; what you survey for is everything that does not belong there. +A GPS L1 C/A signal is BPSK on a 1575.42 MHz carrier, spread by a 1023-chip code at 1.023 Mcps that repeats every 1 ms, with one PRN code per satellite (CDMA). It arrives extremely weak: the GPS SPS Performance Standard guarantees a received signal power of only **-158.5 dBW (-128.5 dBm) for the L1 C/A-code** under the IS-GPS-200 reference conditions, which is below the thermal noise floor, the signal is recovered only by correlating against the known PRN code [spsps2020]. The practical consequence for an SP-layer survey is decisive: **you cannot see the GNSS signal on a waterfall.** A clean, quiet band at L1 *is* the healthy picture; what you survey for is everything that does not belong there. -Because the civilian signal is fixed-frequency, public and arriving below the noise, the entire attack surface at this layer is interference, not secrecy. Interference monitoring is conventionally split into detection/recognition, direction finding, and source location; the detection methods relevant to a single-site survey are **energy detection in the frequency domain (FFT-based)** for a spectrum view, **AGC monitoring** at the RF front end (the receiver's gain control swings under strong in-band power), and **C/N0 (carrier-to-noise) monitoring** in the tracking loops, which falls when interference raises the effective noise [qiao2023survey]. No single metric is sufficient alone: a robust read combines the waterfall with the receiver's own reports. Low-cost COTS receivers, when their C/N0 is paired with a calibrated received-power metric, can separate **nominal, jammed, spoofed and blocked** conditions — jamming collapses C/N0, while a spoof can present as a C/N0 that is implausibly high for the elevated received power (an abnormal imbalance between C/N0 and power that satellite signals, at fixed transmit power, cannot produce) [kriezis2025cots]. +Because the civilian signal is fixed-frequency, public and arriving below the noise, the entire attack surface at this layer is interference, not secrecy. Interference monitoring is conventionally split into detection/recognition, direction finding, and source location; the detection methods relevant to a single-site survey are **energy detection in the frequency domain (FFT-based)** for a spectrum view, **AGC monitoring** at the RF front end (the receiver's gain control swings under strong in-band power), and **C/N0 (carrier-to-noise) monitoring** in the tracking loops, which falls when interference raises the effective noise [qiao2023survey]. No single metric is sufficient alone: a robust read combines the waterfall with the receiver's own reports. Low-cost COTS receivers, when their C/N0 is paired with a calibrated received-power metric, can separate **nominal, jammed, spoofed and blocked** conditions, jamming collapses C/N0, while a spoof can present as a C/N0 that is implausibly high for the elevated received power (an abnormal imbalance between C/N0 and power that satellite signals, at fixed transmit power, cannot produce) [kriezis2025cots]. -Two interference families bound the survey. **Jamming** (broadband noise or a CW carrier over L1) denies the fix — the case the waterfall and a C/N0 collapse make obvious. **Spoofing onset** is subtler: a counterfeit L1 signal slightly stronger than the live sky, detectable here only as an interference *signature* (the spoofing technique itself is an Attack-layer concern). The operational relevance is current: aviation authorities report GNSS jamming and spoofing incidents rising sharply, with GPS signal-loss events up roughly 220% between 2021 and 2024 across Eastern Europe and the Middle East [easa2025gnss]. +Two interference families bound the survey. **Jamming** (broadband noise or a CW carrier over L1) denies the fix, the case the waterfall and a C/N0 collapse make obvious. **Spoofing onset** is subtler: a counterfeit L1 signal slightly stronger than the live sky, detectable here only as an interference *signature* (the spoofing technique itself is an Attack-layer concern). The operational relevance is current: aviation authorities report GNSS jamming and spoofing incidents rising sharply, with GPS signal-loss events up roughly 220% between 2021 and 2024 across Eastern Europe and the Middle East [easa2025gnss]. ## Procedure @@ -138,43 +138,43 @@ All steps are passive receive-only. No transmission is involved at the SP layer, ``` Expected: the command exits without error and the antenna's LNA draws current. A multi-constellation reading benefits from a clear sky view. -2. **Survey the RF environment at L1.** Launch gqrx, tune to 1575.42 MHz, and set a span of roughly 2.5–20 MHz around L1 (RFSAM-RES-01): +2. **Survey the RF environment at L1.** Launch gqrx, tune to 1575.42 MHz, and set a span of roughly 2.5 to 20 MHz around L1 (RFSAM-RES-01): ```text gqrx → Receiver Options → Frequency: 1575.420 MHz Input controls → bias-tee/LNA as needed; FFT span ≈ 8 MHz ``` - Expected (healthy band): a flat noise floor with **no** discrete carrier and **no** wideband hump centred on L1 — you do *not* see the GNSS signal, and that is correct [spsps2020]. Interference tells: a sharp spike (CW jammer), a raised wideband plateau over L1 (broadband jammer), or chirp/sweep streaks on the waterfall. Note the centre frequency, bandwidth and approximate level of anything anomalous [qiao2023survey]. + Expected (healthy band): a flat noise floor with **no** discrete carrier and **no** wideband hump centred on L1, you do *not* see the GNSS signal, and that is correct [spsps2020]. Interference tells: a sharp spike (CW jammer), a raised wideband plateau over L1 (broadband jammer), or chirp/sweep streaks on the waterfall. Note the centre frequency, bandwidth and approximate level of anything anomalous [qiao2023survey]. 3. **Get the receiver-eye view (C/N0 and satellite count).** Plug in the u-blox NEO module and read its per-satellite C/N0 with gpsd: ```bash gpsd -n /dev/ttyACM0 cgps -s # or: gpsmon /dev/ttyACM0 ``` - Expected (healthy): several satellites with C/N0 in roughly the 35–50 dB-Hz range and a 3D fix within a few minutes. **Interference signature:** C/N0 across all tracked satellites drops together and satellites-used falls toward zero (jamming/blocked), versus C/N0 that stays implausibly high for the elevated received power with a stable-but-suspect fix (possible spoof) [kriezis2025cots]. Record C/N0 per PRN and the fix status. + Expected (healthy): several satellites with C/N0 in roughly the 35 to 50 dB-Hz range and a 3D fix within a few minutes. **Interference signature:** C/N0 across all tracked satellites drops together and satellites-used falls toward zero (jamming/blocked), versus C/N0 that stays implausibly high for the elevated received power with a stable-but-suspect fix (possible spoof) [kriezis2025cots]. Record C/N0 per PRN and the fix status. -4. **(Optional) Cross-check with a software receiver on the same I/Q.** If you captured raw L1 I/Q (RFSAM-RES-01), run gnss-sdr and compare its reported C/N0 against the COTS module — agreement strengthens the read and a divergence is itself a finding: +4. **(Optional) Cross-check with a software receiver on the same I/Q.** If you captured raw L1 I/Q (RFSAM-RES-01), run gnss-sdr and compare its reported C/N0 against the COTS module, agreement strengthens the read and a divergence is itself a finding: ```bash gnss-sdr --config_file=gps_l1_survey.conf ``` Expected: per-channel C/N0 estimates consistent with step 3. (Correlation is CPU-intensive; RTL-SDR's ~2.4 MHz bandwidth limits it to single-band L1 C/A.) -5. **Record the baseline.** Note timestamp, site, antenna, SDR, the waterfall observation at L1, and the receiver's C/N0/satellite/fix state. This is the RF-environment baseline that later GNSS steps compare against — and a degraded baseline (jammed/blocked) is the finding for this control. +5. **Record the baseline.** Note timestamp, site, antenna, SDR, the waterfall observation at L1, and the receiver's C/N0/satellite/fix state. This is the RF-environment baseline that later GNSS steps compare against, and a degraded baseline (jammed/blocked) is the finding for this control. ## Field case -Illustrative walkthrough — substitute the values you capture. This is a representative bench survey at a single test site, illustrating how to read the two views rather than reporting a measured incident; the bracketed `[FILL: …]` figures are placeholders to be replaced with your own bench data, not asserted findings. +Illustrative walkthrough, substitute the values you capture. This is a representative bench survey at a single test site, illustrating how to read the two views rather than reporting a measured incident; the bracketed `[FILL: …]` figures are placeholders to be replaced with your own bench data, not asserted findings. Antenna: active L1 patch through a bias-tee into an RTL-SDR V4 (`rtl_biast -b 1`), with a u-blox NEO-class module on `/dev/ttyACM0` for the receiver-eye view. -- **Nominal baseline.** gqrx at 1575.420 MHz showed a flat noise floor with no carrier over L1 — the expected "healthy = nothing visible" picture, since the C/A signal sits at about -128.5 dBm, below the noise [spsps2020]. For a documented reference reading, the GNSS-SDR project's own monitoring example — running the software receiver over its public sample recording `2013_04_04_GNSS_SIGNAL_at_CTTC_SPAIN.dat` — tracks **5 GPS satellites** (PRN 1, 11, 17, 20, 32) with C/N0 of **42–45 dB-Hz** (42.4 to 45.3 dB-Hz across the five channels), a healthy picture sitting in the 35–50 dB-Hz band [gnsssdr2013monitor]. That is the shape `cgps -s` should report on a clean band: a 3D fix on a comparable handful of satellites with C/N0 in that range. -- **Injected interference (contained).** With a CW source placed on L1 in a contained setup, gqrx showed a discrete spike at 1575.42 MHz rising above the floor; simultaneously C/N0 on every tracked PRN fell together and satellites-used dropped to [FILL: N], losing the fix — the jamming signature: a tell on the waterfall *and* a coordinated C/N0 collapse [qiao2023survey][kriezis2025cots]. +- **Nominal baseline.** gqrx at 1575.420 MHz showed a flat noise floor with no carrier over L1, the expected "healthy = nothing visible" picture, since the C/A signal sits at about -128.5 dBm, below the noise [spsps2020]. For a documented reference reading, the GNSS-SDR project's own monitoring example, running the software receiver over its public sample recording `2013_04_04_GNSS_SIGNAL_at_CTTC_SPAIN.dat`, tracks **5 GPS satellites** (PRN 1, 11, 17, 20, 32) with C/N0 of **42 to 45 dB-Hz** (42.4 to 45.3 dB-Hz across the five channels), a healthy picture sitting in the 35 to 50 dB-Hz band [gnsssdr2013monitor]. That is the shape `cgps -s` should report on a clean band: a 3D fix on a comparable handful of satellites with C/N0 in that range. +- **Injected interference (contained).** With a CW source placed on L1 in a contained setup, gqrx showed a discrete spike at 1575.42 MHz rising above the floor; simultaneously C/N0 on every tracked PRN fell together and satellites-used dropped to [FILL: N], losing the fix, the jamming signature: a tell on the waterfall *and* a coordinated C/N0 collapse [qiao2023survey][kriezis2025cots]. -The point is the two-view method: the waterfall says *something is on L1*, and the receiver's C/N0/satellite count says *and it is denying the fix*. Either alone is weaker than both together. The real-world stakes are not hypothetical — aviation regulators report GPS signal-loss events up roughly 220% from 2021 to 2024 across affected regions [easa2025gnss]. +The point is the two-view method: the waterfall says *something is on L1*, and the receiver's C/N0/satellite count says *and it is denying the fix*. Either alone is weaker than both together. The real-world stakes are not hypothetical, aviation regulators report GPS signal-loss events up roughly 220% from 2021 to 2024 across affected regions [easa2025gnss]. ## Remediation GNSS interference at the SP layer is a resilience-and-detection problem, not a confidentiality one (there is no key to protect); remediation is layered. -- **Developer (receiver / firmware).** Expose AGC level, C/N0 per satellite, and an interference/jamming flag in the receiver's output so downstream systems can *see* a degraded band rather than silently trusting a fix; many u-blox-class modules already surface jamming/interference indicators — consume them [qiao2023survey]. Implement consistency/RAIM checks so an implausible solution is rejected rather than accepted. -- **Integrator (system).** Do not let a single GNSS input be a single point of failure: hold over an internal clock or alternate timing source when C/N0/AGC indicate interference, and combine GNSS with inertial or other navigation so a denied or spoofed fix degrades gracefully [kriezis2025cots]. Prefer multi-constellation, multi-band receivers — a survey covering L1/L2/L5 across GPS/Galileo/GLONASS/BeiDou is harder to deny than GPS-L1-only. -- **Operator.** Run this survey as a periodic baseline so a *new* carrier or C/N0 collapse is detectable as a change, alarm on signal-loss rather than coasting silently, and report suspected interference through the appropriate channel — aviation and maritime authorities now run formal GNSS-interference reporting and mitigation programmes [easa2025gnss]. +- **Developer (receiver / firmware).** Expose AGC level, C/N0 per satellite, and an interference/jamming flag in the receiver's output so downstream systems can *see* a degraded band rather than silently trusting a fix; many u-blox-class modules already surface jamming/interference indicators, consume them [qiao2023survey]. Implement consistency/RAIM checks so an implausible solution is rejected rather than accepted. +- **Integrator (system).** Do not let a single GNSS input be a single point of failure: hold over an internal clock or alternate timing source when C/N0/AGC indicate interference, and combine GNSS with inertial or other navigation so a denied or spoofed fix degrades gracefully [kriezis2025cots]. Prefer multi-constellation, multi-band receivers, a survey covering L1/L2/L5 across GPS/Galileo/GLONASS/BeiDou is harder to deny than GPS-L1-only. +- **Operator.** Run this survey as a periodic baseline so a *new* carrier or C/N0 collapse is detectable as a change, alarm on signal-loss rather than coasting silently, and report suspected interference through the appropriate channel, aviation and maritime authorities now run formal GNSS-interference reporting and mitigation programmes [easa2025gnss]. diff --git a/src/content/controls/rfsam-gsm-cr-01.md b/src/content/controls/rfsam-gsm-cr-01.md index f6a0696..53a1fc2 100644 --- a/src/content/controls/rfsam-gsm-cr-01.md +++ b/src/content/controls/rfsam-gsm-cr-01.md @@ -11,8 +11,8 @@ deferred: false objective: >- Determine, from passive capture of a GSM cell, which A5 ciphering algorithm the network negotiates (A5/0 none, A5/1, A5/2, or A5/3) and whether subscriber - identities are exposed on the air — i.e. whether the cell ever pages or - identity-requests the permanent IMSI rather than a temporary TMSI — establishing + identities are exposed on the air, i.e. whether the cell ever pages or + identity-requests the permanent IMSI rather than a temporary TMSI, establishing whether the session is confidentiality-protected and whether subscribers are trackable. intro: >- @@ -27,7 +27,7 @@ intro: >- prerequisites: hardware: - 'An RTL-SDR V4 reaches GSM-850/900 and DCS-1800; for PCS-1900 (top of the RTL-SDR range) prefer a HackRF One, bladeRF 2.0 micro, or USRP B210' - - 'Reception only — this control transmits nothing' + - 'Reception only, this control transmits nothing' software: - 'kalibrate-rtl to find a live ARFCN; gr-gsm (grgsm_livemon) to demodulate and decode the downlink; Wireshark to read the GSMTAP stream; Oros42 IMSI-catcher to extract paged identities; Kraken + the A5/1 rainbow tables only for the authorised lab key-recovery step' signal: @@ -50,8 +50,8 @@ attacks: in modern handsets, so this is chiefly a legacy / lab finding. summary: >- The foundational ciphertext-only attack on A5/2 and the active downgrade that - undermines A5/1, establishing why the negotiated A5 algorithm — not just its - presence — is the finding. + undermines A5/1, establishing why the negotiated A5 algorithm, not just its + presence, is the finding. - name: A5/1 rainbow-table key recovery refs: - nohl2009gsm @@ -61,7 +61,7 @@ attacks: decrypts. preconditions: >- The cell runs A5/1, the capture contains a recoverable known-keystream segment, - and the operator holds the ~1.6–2 TB rainbow tables. Heavy but public. No effect + and the operator holds the ~1.6 to 2 TB rainbow tables. Heavy but public. No effect on A5/3 (KASUMI). summary: >- The Berlin A5/1 Security Project's public rainbow tables, presented as @@ -79,7 +79,7 @@ attacks: preconditions: >- Passive finding: the cell exposes the IMSI on the air (no valid TMSI held, or during location update). The active variant needs a rogue cell (out of scope - for this passive control — see the AT-layer control). + for this passive control, see the AT-layer control). summary: >- GSM authenticates one-way, so on-air IMSI exposure is both a privacy finding and the signature an active IMSI catcher relies on; this control measures the @@ -93,7 +93,7 @@ references: url: 'https://www.iacr.org/archive/crypto2003/27290598/27290598.pdf' type: paper - key: nohl2009gsm - title: GSM — SRSLY? (A5/1 rainbow tables / Berlin A5/1 Security Project) + title: GSM, SRSLY? (A5/1 rainbow tables / Berlin A5/1 Security Project) authors: 'K. Nohl, C. Paget' venue: 26th Chaos Communication Congress (26C3), Berlin year: 2009 @@ -144,15 +144,15 @@ lastResearched: 2026-06-14 ## Mechanism -GSM confidentiality is supplied by the A5 family of ciphers, applied to the radio link after the network sends a Cipher Mode Command naming the algorithm to use. The algorithm in force is therefore *readable on the air* from that L3 signalling message — it is the single most decisive fact about the link. A5/0 is no ciphering at all; A5/1 is a 64-bit stream cipher; A5/2 is an export-weakened variant; A5/3 and A5/4 use the KASUMI block cipher and are far stronger [welte2010a52]. The negotiated algorithm matters more than its mere presence because the weaker options are publicly broken. +GSM confidentiality is supplied by the A5 family of ciphers, applied to the radio link after the network sends a Cipher Mode Command naming the algorithm to use. The algorithm in force is therefore *readable on the air* from that L3 signalling message, it is the single most decisive fact about the link. A5/0 is no ciphering at all; A5/1 is a 64-bit stream cipher; A5/2 is an export-weakened variant; A5/3 and A5/4 use the KASUMI block cipher and are far stronger [welte2010a52]. The negotiated algorithm matters more than its mere presence because the weaker options are publicly broken. -A5/2 falls to a **ciphertext-only** attack: Barkan, Biham and Keller showed that a few dozen milliseconds of A5/2 ciphertext yield the session key in under a second on a PC, and — crucially — because A5/1 and A5/2 derive the session key Kc the same way, an active man-in-the-middle can issue a Cipher Mode Command that forces a handset down to A5/2, recover Kc, and use it to decrypt traffic that was actually recorded under A5/1 [barkan2003instant]. This shared-key-generation downgrade is why A5/2 was eventually withdrawn from handsets entirely, a process Welte documents [welte2010a52]. A5/1 itself was moved from theory to off-the-shelf capability by the Berlin A5/1 Security Project: precomputed rainbow tables (~1.6–2 TB), published as "GSM SRSLY?" at 26C3, recover the 64-bit Kc from a known-keystream slice, after which the rest of the captured A5/1 call or SMS decrypts [nohl2009gsm]. None of this touches A5/3 (KASUMI), so confirming an A5/3 cell is a materially stronger result than confirming A5/1. +A5/2 falls to a **ciphertext-only** attack: Barkan, Biham and Keller showed that a few dozen milliseconds of A5/2 ciphertext yield the session key in under a second on a PC, and, crucially, because A5/1 and A5/2 derive the session key Kc the same way, an active man-in-the-middle can issue a Cipher Mode Command that forces a handset down to A5/2, recover Kc, and use it to decrypt traffic that was actually recorded under A5/1 [barkan2003instant]. This shared-key-generation downgrade is why A5/2 was eventually withdrawn from handsets entirely, a process Welte documents [welte2010a52]. A5/1 itself was moved from theory to off-the-shelf capability by the Berlin A5/1 Security Project: precomputed rainbow tables (~1.6 to 2 TB), published as "GSM SRSLY?" at 26C3, recover the 64-bit Kc from a known-keystream slice, after which the rest of the captured A5/1 call or SMS decrypts [nohl2009gsm]. None of this touches A5/3 (KASUMI), so confirming an A5/3 cell is a materially stronger result than confirming A5/1. -The second axis is identity. The permanent subscriber identity (IMSI) is meant to be hidden behind a network-assigned temporary identity (TMSI); the IMSI is only supposed to appear on the air during attach or location update when no valid TMSI is held. The network can, however, compel disclosure: the Identification procedure of the L3 mobility-management protocol lets the network send an Identity Request for the IMSI or IMEI, which the handset answers [3gpp24008]. Because GSM authentication is **one-way** — the handset authenticates to the network, but the network never proves itself to the handset — a passive observer that sees the cell paging by IMSI, or sees an IMSI in an Identity Response, has both a privacy finding (the subscriber is trackable) and the on-air signature that an active IMSI catcher exploits by impersonating the cell and demanding the IMSI plus weak or absent ciphering [dabrowski2014imsi]. This control measures the *passive* exposure; the active rogue-cell technique is authorised-testing-only and belongs to the GSM AT-layer control. +The second axis is identity. The permanent subscriber identity (IMSI) is meant to be hidden behind a network-assigned temporary identity (TMSI); the IMSI is only supposed to appear on the air during attach or location update when no valid TMSI is held. The network can, however, compel disclosure: the Identification procedure of the L3 mobility-management protocol lets the network send an Identity Request for the IMSI or IMEI, which the handset answers [3gpp24008]. Because GSM authentication is **one-way**, the handset authenticates to the network, but the network never proves itself to the handset, a passive observer that sees the cell paging by IMSI, or sees an IMSI in an Identity Response, has both a privacy finding (the subscriber is trackable) and the on-air signature that an active IMSI catcher exploits by impersonating the cell and demanding the IMSI plus weak or absent ciphering [dabrowski2014imsi]. This control measures the *passive* exposure; the active rogue-cell technique is authorised-testing-only and belongs to the GSM AT-layer control. ## Procedure -All steps are **passive reception** of what the network already broadcasts, on equipment you own or are authorised to test. Step 5 (key recovery) decrypts traffic and is **authorised-testing-only**: a licensed lab or RF-shielded enclosure with explicit permission and your own test SIMs — recovering keys from live traffic you are not authorised to intercept is illegal in most jurisdictions. +All steps are **passive reception** of what the network already broadcasts, on equipment you own or are authorised to test. Step 5 (key recovery) decrypts traffic and is **authorised-testing-only**: a licensed lab or RF-shielded enclosure with explicit permission and your own test SIMs, recovering keys from live traffic you are not authorised to intercept is illegal in most jurisdictions. 1. **Find a live cell and its ARFCN.** Sweep the regional band with kalibrate to list carriers with a live BTS, their power, and the radio's clock error: ```bash @@ -162,7 +162,7 @@ All steps are **passive reception** of what the network already broadcasts, on e ```bash kal -c 12 -g 40 ``` - Expected: an `average absolute error: ppm` line — note that ppm for the next step. (Use a HackRF/UHD kalibrate fork instead of `kal` (`kalibrate-rtl`) for those radios; PCS-1900 needs a HackRF/bladeRF/USRP.) + Expected: an `average absolute error: ppm` line, note that ppm for the next step. (Use a HackRF/UHD kalibrate fork instead of `kal` (`kalibrate-rtl`) for those radios; PCS-1900 needs a HackRF/bladeRF/USRP.) 2. **Demodulate and decode the downlink.** Tune the found ARFCN's downlink frequency with gr-gsm, applying the ppm correction: ```bash @@ -174,7 +174,7 @@ All steps are **passive reception** of what the network already broadcasts, on e ```bash sudo wireshark -k -i lo -f 'udp port 4729' -Y 'gsmtap' ``` - Confirm System Information, paging and assignment frames are scrolling — this proves the decode chain is working before you assess crypto or identity. + Confirm System Information, paging and assignment frames are scrolling, this proves the decode chain is working before you assess crypto or identity. 4. **Determine the negotiated A5 algorithm.** In Wireshark, filter for the cipher-mode signalling: ```text @@ -183,12 +183,12 @@ All steps are **passive reception** of what the network already broadcasts, on e Open the **Cipher Mode Command** and read the *Cipher Mode Setting* / algorithm identifier: it states A5/0 (no ciphering), A5/1, A5/2, or A5/3. This is the control's primary verdict. A cell that sets A5/0 or A5/2 is a finding on its own [barkan2003instant]; A5/1 is breakable with the rainbow tables [nohl2009gsm]; A5/3 is the hardened case. 5. **Assess identity exposure.** Two checks: - - In Wireshark, inspect **Paging Request** messages — filter `gsm_a.dtap` and look at the mobile-identity IE: if the cell pages by **IMSI** (rather than TMSI), or you see an **Identity Request** for the IMSI followed by an **Identity Response** carrying it, the permanent identity is exposed [3gpp24008]. + - In Wireshark, inspect **Paging Request** messages, filter `gsm_a.dtap` and look at the mobile-identity IE: if the cell pages by **IMSI** (rather than TMSI), or you see an **Identity Request** for the IMSI followed by an **Identity Response** carrying it, the permanent identity is exposed [3gpp24008]. - Cross-check passively with the Oros42 IMSI-catcher, which consumes the same GSMTAP stream and prints harvested identities: ```bash python3 simple_IMSI-catcher.py --sniff ``` - Expected: lines pairing TMSI/IMSI with country/operator for handsets the cell pages — concrete evidence of on-air identity exposure with **no transmission** [dabrowski2014imsi]. + Expected: lines pairing TMSI/IMSI with country/operator for handsets the cell pages, concrete evidence of on-air identity exposure with **no transmission** [dabrowski2014imsi]. 6. **(Authorised lab only) Recover the A5/1 key.** Where the cell runs A5/1 and you are authorised to decrypt, isolate a burst with a recoverable known-keystream segment from the capture and feed it to Kraken against the rainbow tables to recover Kc, which then decrypts the rest of the captured A5/1 session [nohl2009gsm]: ```bash @@ -199,12 +199,12 @@ All steps are **passive reception** of what the network already broadcasts, on e ## Field case -Worked from a public sample capture rather than a live target: gr-gsm ships the SRLabs "Airprobe How-To" capture `vf_call6_a725_d174_g5_Kc1EF00BAB3BAC7002.cfile` (ptrkrysik/test_data; the README records its SRLabs origin), and the gr-gsm "Usage: Decoding How-To" wiki plus the project's CI decode fixtures replay it end to end [grgsmtestdata]. Decoding it with `grgsm_decode -c vf_call6_a725_d174_g5_Kc1EF00BAB3BAC7002.cfile -s $((100000000/174)) -a 725 -m BCCH -t 0` (decimation 174, so a 100e6/174 sample rate) confirms the carrier on **ARFCN 725 (E-GSM-900 downlink)**, and re-running on the SDCCH8 with the recovered key (`-m SDCCH8 -t 1 -e 1 -k 0x1E,0xF0,0x0B,0xAB,0x3B,0xAC,0x70,0x02`) decrypts the session. In the decrypted SDCCH8 fixture the **RR Cipher Mode Command** carries a Cipher Mode Setting whose start-ciphering bit is set with algorithm identifier `000`, i.e. **A5/1**; the recovered 64-bit A5/1 session key is `Kc = 1E F0 0B AB 3B AC 70 02`. The identity exchanged on the air is **TMSI only** — the paging / identity IEs carry P-TMSI values (e.g. `0x014faf9a`, `0x015c5703`); no IMSI is exposed in the documented decode [grgsmtestdata]. Findings for this public sample: +Worked from a public sample capture rather than a live target: gr-gsm ships the SRLabs "Airprobe How-To" capture `vf_call6_a725_d174_g5_Kc1EF00BAB3BAC7002.cfile` (ptrkrysik/test_data; the README records its SRLabs origin), and the gr-gsm "Usage: Decoding How-To" wiki plus the project's CI decode fixtures replay it end to end [grgsmtestdata]. Decoding it with `grgsm_decode -c vf_call6_a725_d174_g5_Kc1EF00BAB3BAC7002.cfile -s $((100000000/174)) -a 725 -m BCCH -t 0` (decimation 174, so a 100e6/174 sample rate) confirms the carrier on **ARFCN 725 (E-GSM-900 downlink)**, and re-running on the SDCCH8 with the recovered key (`-m SDCCH8 -t 1 -e 1 -k 0x1E,0xF0,0x0B,0xAB,0x3B,0xAC,0x70,0x02`) decrypts the session. In the decrypted SDCCH8 fixture the **RR Cipher Mode Command** carries a Cipher Mode Setting whose start-ciphering bit is set with algorithm identifier `000`, i.e. **A5/1**; the recovered 64-bit A5/1 session key is `Kc = 1E F0 0B AB 3B AC 70 02`. The identity exchanged on the air is **TMSI only**, the paging / identity IEs carry P-TMSI values (e.g. `0x014faf9a`, `0x015c5703`); no IMSI is exposed in the documented decode [grgsmtestdata]. Findings for this public sample: - ARFCN / downlink: ARFCN 725 (E-GSM-900 downlink), decoded at sample rate 100e6/174 (decimation 174) [grgsmtestdata] -- Cipher Mode Command algorithm: A5/1 (Cipher Mode Setting byte `0x11` — start-ciphering bit set, algorithm identifier `000` = A5/1); recovered session key `Kc = 1E F0 0B AB 3B AC 70 02` [grgsmtestdata] -- Identity seen on the air: TMSI only — P-TMSI values such as `0x014faf9a` and `0x015c5703`; no IMSI exposed in the documented decode [grgsmtestdata] -- Verdict: A5/1 in force — a publicly broken cipher whose 64-bit Kc is recoverable from the captured keystream (here `1E F0 0B AB 3B AC 70 02`), so a confidentiality finding; identity handling is sound for this sample (TMSI only, no IMSI on the air) [grgsmtestdata] +- Cipher Mode Command algorithm: A5/1 (Cipher Mode Setting byte `0x11`, start-ciphering bit set, algorithm identifier `000` = A5/1); recovered session key `Kc = 1E F0 0B AB 3B AC 70 02` [grgsmtestdata] +- Identity seen on the air: TMSI only, P-TMSI values such as `0x014faf9a` and `0x015c5703`; no IMSI exposed in the documented decode [grgsmtestdata] +- Verdict: A5/1 in force, a publicly broken cipher whose 64-bit Kc is recoverable from the captured keystream (here `1E F0 0B AB 3B AC 70 02`), so a confidentiality finding; identity handling is sound for this sample (TMSI only, no IMSI on the air) [grgsmtestdata] This is a documented public example, not a live interception: the capture, the decode commands, the negotiated A5/1, the recovered Kc and the TMSI-only identity behaviour are all taken from the gr-gsm sample capture and its wiki / CI fixtures [grgsmtestdata]. Against your own authorised target, substitute the ARFCN, A5 algorithm and identity finding you actually measure; no claim is made about any production network. @@ -214,4 +214,4 @@ This is a documented public example, not a live interception: the capture, the d **Integrator (device OEMs / IoT product owners).** For new designs, do not ship 2G-only radios for anything carrying sensitive data; where 2G is a fallback, treat the GSM link as unauthenticated and unconfidential by default and add end-to-end application-layer encryption and authentication above it, so an exposed IMSI or a recovered Kc does not yield plaintext. Disable 2G entirely on devices that do not need it, removing the downgrade target. -**Operator (network / defenders / assessors).** Run A5/3 and disable A5/1 and A5/2 on the radio network; A5/2 was withdrawn from handsets precisely because of the downgrade-to-A5/2 break [welte2010a52]. Minimise IMSI exposure by reallocating TMSIs promptly and avoiding IMSI paging, since frequent IMSI exposure is both a privacy weakness and the signature of an active IMSI catcher [dabrowski2014imsi] [3gpp24008]. For assessors: the cipher-and-identity read in steps 1–5 is fully passive and safe to run on equipment you are authorised to monitor; the key-recovery step 6 and any active rogue-cell work are authorised-testing-only (own equipment, test SIMs, RF shielding, explicit permission). There is no BSAM cellular control to defer to — this is RFSAM's domain. +**Operator (network / defenders / assessors).** Run A5/3 and disable A5/1 and A5/2 on the radio network; A5/2 was withdrawn from handsets precisely because of the downgrade-to-A5/2 break [welte2010a52]. Minimise IMSI exposure by reallocating TMSIs promptly and avoiding IMSI paging, since frequent IMSI exposure is both a privacy weakness and the signature of an active IMSI catcher [dabrowski2014imsi] [3gpp24008]. For assessors: the cipher-and-identity read in steps 1 to 5 is fully passive and safe to run on equipment you are authorised to monitor; the key-recovery step 6 and any active rogue-cell work are authorised-testing-only (own equipment, test SIMs, RF shielding, explicit permission). There is no BSAM cellular control to defer to, this is RFSAM's domain. diff --git a/src/content/controls/rfsam-gsm-sp-01.md b/src/content/controls/rfsam-gsm-sp-01.md index 5c720bd..5b07e0d 100644 --- a/src/content/controls/rfsam-gsm-sp-01.md +++ b/src/content/controls/rfsam-gsm-sp-01.md @@ -10,13 +10,13 @@ deferred: false objective: >- Establish which GSM carriers (ARFCNs) carry a live base station in the target band, record each carrier's strength, ARFCN and the receiver's clock error, and - confirm at least one BCCH carrier falls inside the receiver's tuning envelope — + confirm at least one BCCH carrier falls inside the receiver's tuning envelope, the spectrum-layer prerequisite that scopes every later GSM capture control. intro: >- A GSM carrier is a 200 kHz channel indexed by ARFCN, and a downlink BCCH carrier transmits continuously, so cells show as steady 200 kHz pickets in the waterfall. The reliable way to find them is to scan for the FCCH/SCH synchronisation bursts - every BTS emits — which also yields each carrier's ARFCN, its power and the + every BTS emits, which also yields each carrier's ARFCN, its power and the radio's clock offset (ppm). This control records that carrier inventory and confirms a captureable channel; it is an environmental baseline, not a device finding. Receiving broadcast information is passive, but anything that transmits @@ -26,10 +26,10 @@ prerequisites: - 'A receive SDR covering the target band: RTL-SDR Blog V4 reaches GSM-850/900 and DCS-1800; PCS-1900 is at the top of its range, so prefer HackRF One / bladeRF 2.0 / USRP B210 there' - 'A clean antenna for the band in use (850/900 or 1800/1900 MHz)' software: - - 'kalibrate-rtl (kal) — sweeps a GSM band for live BTS carriers and reports ARFCN, power and ppm clock offset; use the matching HackRF/UHD kalibrate fork for those radios' + - 'kalibrate-rtl (kal), sweeps a GSM band for live BTS carriers and reports ARFCN, power and ppm clock offset; use the matching HackRF/UHD kalibrate fork for those radios' - 'gqrx for the live spectrum/waterfall sanity check' signal: - freq: 'GSM-850 / E-GSM-900 / DCS-1800 / PCS-1900 — band depends on region (900/1800 most of the world, 850/1900 in the Americas); FDD, downlink/uplink spaced 45 MHz (900) / 95 MHz (1800)' + freq: 'GSM-850 / E-GSM-900 / DCS-1800 / PCS-1900, band depends on region (900/1800 most of the world, 850/1900 in the Americas); FDD, downlink/uplink spaced 45 MHz (900) / 95 MHz (1800)' bandwidth: '200 kHz per ARFCN carrier; each carrier is TDMA-divided into 8 timeslots' modulation: 'GMSK (0.3 BT Gaussian-filtered MSK) at 270.833 kbit/s; EDGE adds 8-PSK' skill: intermediate @@ -40,7 +40,7 @@ attacks: impact: >- The carrier survey is the first step of GSM identity reconnaissance: once a BCCH carrier is found and demodulated, the cell pages handsets and, during - attach / location update, exposes the IMSI in the clear — harvestable + attach / location update, exposes the IMSI in the clear, harvestable passively with no transmit, and the same broadcast an IMSI catcher mimics. preconditions: >- GSM authenticates the network to the phone one-way only (the cell never @@ -54,12 +54,12 @@ attacks: control performs. references: - key: ts45005 - title: '3GPP TS 45.005 — GSM/EDGE Radio transmission and reception (200 kHz channel spacing, ARFCN, GMSK 270.833 kbit/s)' + title: '3GPP TS 45.005, GSM/EDGE Radio transmission and reception (200 kHz channel spacing, ARFCN, GMSK 270.833 kbit/s)' venue: 3GPP url: 'https://portal.3gpp.org/desktopmodules/Specifications/SpecificationDetails.aspx?specificationId=2709' type: standard - key: ts45002 - title: '3GPP TS 45.002 — GSM/EDGE Multiplexing and multiple access on the radio path (FCCH/SCH bursts, 51-multiframe, BCCH/CCCH/SDCCH/TCH logical channels, 8-slot TDMA)' + title: '3GPP TS 45.002, GSM/EDGE Multiplexing and multiple access on the radio path (FCCH/SCH bursts, 51-multiframe, BCCH/CCCH/SDCCH/TCH logical channels, 8-slot TDMA)' venue: 3GPP url: 'https://portal.3gpp.org/desktopmodules/Specifications/SpecificationDetails.aspx?specificationId=2706' type: standard @@ -76,19 +76,19 @@ references: url: 'https://ics.uci.edu/~dabrowsa/dabrowski-acsac14-IMSICatcherCatcher.pdf' type: paper - key: kalibrate - title: 'kalibrate-rtl — GSM frequency scanner / clock-offset calculator (RTL-SDR fork of Joshua Lackey''s kalibrate)' + title: 'kalibrate-rtl, GSM frequency scanner / clock-offset calculator (RTL-SDR fork of Joshua Lackey''s kalibrate)' authors: steve-m (fork) venue: GitHub url: 'https://github.com/steve-m/kalibrate-rtl' type: tool - key: grgsm - title: 'gr-gsm — GNU Radio blocks and tools for receiving GSM transmissions (grgsm_livemon → GSMTAP)' + title: 'gr-gsm, GNU Radio blocks and tools for receiving GSM transmissions (grgsm_livemon → GSMTAP)' authors: P. Krysik (ptrkrysik) venue: GitHub url: 'https://github.com/ptrkrysik/gr-gsm' type: tool - key: imsicatcher - title: 'IMSI-catcher — passive IMSI/TMSI extractor reading gr-gsm''s GSMTAP stream' + title: 'IMSI-catcher, passive IMSI/TMSI extractor reading gr-gsm''s GSMTAP stream' authors: Oros42 venue: GitHub url: 'https://github.com/Oros42/IMSI-catcher' @@ -110,18 +110,18 @@ lastResearched: 2026-06-14 --- ## Mechanism -A GSM deployment is a grid of cells, each served by a base station (BTS) that broadcasts on one or more 200 kHz carriers. The carrier is identified by its Absolute Radio Frequency Channel Number (ARFCN): the carrier-to-frequency mapping, the 200 kHz channel spacing and the GMSK modulation at 270.833 kbit/s are defined in 3GPP TS 45.005 [ts45005]. Bands are regional — GSM-850 / E-GSM-900 in the Americas and the 900/1800 split elsewhere — and the ARFCN ranges and the FDD duplex offsets (45 MHz on the 900 band, 95 MHz on the 1800 band) follow the standard band plan [arfcn][ts45005]. Each carrier is divided by TDMA into 8 timeslots, so one 200 kHz channel carries up to 8 logical-channel streams [ts45002]. +A GSM deployment is a grid of cells, each served by a base station (BTS) that broadcasts on one or more 200 kHz carriers. The carrier is identified by its Absolute Radio Frequency Channel Number (ARFCN): the carrier-to-frequency mapping, the 200 kHz channel spacing and the GMSK modulation at 270.833 kbit/s are defined in 3GPP TS 45.005 [ts45005]. Bands are regional, GSM-850 / E-GSM-900 in the Americas and the 900/1800 split elsewhere, and the ARFCN ranges and the FDD duplex offsets (45 MHz on the 900 band, 95 MHz on the 1800 band) follow the standard band plan [arfcn][ts45005]. Each carrier is divided by TDMA into 8 timeslots, so one 200 kHz channel carries up to 8 logical-channel streams [ts45002]. -Because a downlink BCCH carrier transmits continuously, a live cell shows on a waterfall as a steady 200 kHz picket. But the reliable detector is the synchronisation structure rather than the eye: every BTS sends a Frequency Correction Channel (FCCH) burst and a Synchronisation Channel (SCH) burst in timeslot 0 of the BCCH carrier, on a fixed schedule within the 51-frame control multiframe [ts45002]. The FCCH burst is an all-zeros sequence that, after GMSK modulation, produces a pure tone at one quarter of the bit rate — (1625000/6)/4 ≈ 67.708 kHz above the carrier — so a receiver can find a GSM carrier, and measure its own oscillator error, by searching each candidate channel for that tone [ts45002][kalibrate]. This is exactly what `kalibrate` does: it sweeps a band, reports every ARFCN with a live BTS, its relative power, and the ppm clock offset to feed forward into the capture step [kalibrate]. +Because a downlink BCCH carrier transmits continuously, a live cell shows on a waterfall as a steady 200 kHz picket. But the reliable detector is the synchronisation structure rather than the eye: every BTS sends a Frequency Correction Channel (FCCH) burst and a Synchronisation Channel (SCH) burst in timeslot 0 of the BCCH carrier, on a fixed schedule within the 51-frame control multiframe [ts45002]. The FCCH burst is an all-zeros sequence that, after GMSK modulation, produces a pure tone at one quarter of the bit rate, (1625000/6)/4 ≈ 67.708 kHz above the carrier, so a receiver can find a GSM carrier, and measure its own oscillator error, by searching each candidate channel for that tone [ts45002][kalibrate]. This is exactly what `kalibrate` does: it sweeps a band, reports every ARFCN with a live BTS, its relative power, and the ppm clock offset to feed forward into the capture step [kalibrate]. -The survey is also the entry point of GSM identity reconnaissance. GSM authenticates the network to the phone one-way only — the cell never proves itself — and the broadcast/synchronisation channels are unprotected, so any receiver in range can locate the carrier and read the cell's broadcast without a credential [dabrowski2014]. Once the BCCH carrier is demodulated, the cell pages handsets and, during attach / location update, exposes the IMSI in the clear; Dabrowski et al. show this cleartext identity exposure and one-way authentication are what make passive identity collection and fake-base-station IMSI catchers practical [dabrowski2014]. This control owns the spectrum-layer half — find the live carrier and confirm it is captureable; the GMSK demodulation and BCCH/CCCH/SDCCH decode are the work of the GSM capture (PHY/LL) controls, which run gr-gsm on the ARFCN found here [grgsm]. +The survey is also the entry point of GSM identity reconnaissance. GSM authenticates the network to the phone one-way only, the cell never proves itself, and the broadcast/synchronisation channels are unprotected, so any receiver in range can locate the carrier and read the cell's broadcast without a credential [dabrowski2014]. Once the BCCH carrier is demodulated, the cell pages handsets and, during attach / location update, exposes the IMSI in the clear; Dabrowski et al. show this cleartext identity exposure and one-way authentication are what make passive identity collection and fake-base-station IMSI catchers practical [dabrowski2014]. This control owns the spectrum-layer half, find the live carrier and confirm it is captureable; the GMSK demodulation and BCCH/CCCH/SDCCH decode are the work of the GSM capture (PHY/LL) controls, which run gr-gsm on the ARFCN found here [grgsm]. ## Procedure -> Authorised testing only. Every step below is receive-only — you read what the +> Authorised testing only. Every step below is receive-only, you read what the > network already broadcasts. Do not transmit on licensed cellular spectrum. -1. **Pick the band for your region and confirm your radio reaches it.** Decide which GSM band the operators use locally — GSM-850/900 and DCS-1800 are within an RTL-SDR Blog V4's range; PCS-1900 sits at the top of its tuning range, so prefer a HackRF / bladeRF / USRP there [ts45005][arfcn]. +1. **Pick the band for your region and confirm your radio reaches it.** Decide which GSM band the operators use locally, GSM-850/900 and DCS-1800 are within an RTL-SDR Blog V4's range; PCS-1900 sits at the top of its tuning range, so prefer a HackRF / bladeRF / USRP there [ts45005][arfcn]. 2. **Sweep the band for live carriers with kalibrate.** Point `kal` at the chosen band and let it lock onto FCCH/SCH bursts: ```bash @@ -154,22 +154,22 @@ The survey is also the entry point of GSM identity reconnaissance. GSM authentic ``` In the GUI set the device to your SDR, tune to the ARFCN's centre frequency and watch the waterfall. A live downlink BCCH carrier shows as a steady, continuous ~200 kHz block; confirm its width and that it does not drift, then note its centre frequency [ts45005]. -5. **Record the inventory.** For each carrier capture: band, ARFCN, downlink centre frequency, relative power, and the measured ppm offset. Mark which carriers fall inside your SDR's tuning envelope (RFSAM-RES-01) — those are the sniffable targets that scope the GSM capture controls, which run gr-gsm on the chosen ARFCN to demodulate and decode the downlink [grgsm]. +5. **Record the inventory.** For each carrier capture: band, ARFCN, downlink centre frequency, relative power, and the measured ppm offset. Mark which carriers fall inside your SDR's tuning envelope (RFSAM-RES-01), those are the sniffable targets that scope the GSM capture controls, which run gr-gsm on the chosen ARFCN to demodulate and decode the downlink [grgsm]. ## Field case -> Authorised testing only — receive-only carrier survey on your own equipment. +> Authorised testing only, receive-only carrier survey on your own equipment. The kalibrate-rtl README ships a documented example of exactly this workflow, which we use here as a public reference run rather than our own live capture; reproduce the same steps on your own authorised equipment and record your own ARFCN, power and ppm before treating any number as an engagement finding. -In the README's documented GSM-850 scan, `kal -s GSM850` surfaces several live ARFCNs and the strongest reading is `chan: 145 (872.6MHz - 7Hz) power: 33605.48` [kalibrate]. Re-running `kal -c 145` on that carrier averages the FCCH tone into a tight clock offset — `average -1Hz [-8, 7] (range 14, stddev 3.948722)` with `overruns: 0` and `not found: 0` — a clean lock to carry forward (current kalibrate-rtl builds print the equivalent trailing line as an `average absolute error: %.3f ppm` figure, per `src/offset.cc`) [kalibrate]. Tuning gqrx to that centre would confirm a steady 200 kHz downlink picket. Carried forward into the capture step, `grgsm_livemon -f 872.6M` on the same ARFCN (with the measured offset) demodulates the BCCH and streams GSMTAP into Wireshark — at which point the Oros42 IMSI-catcher reads the GSMTAP feed and prints the IMSI/TMSI the cell pages, with no transmit [grgsm][imsicatcher]. The carrier survey is the prerequisite: without the ARFCN, power and offset from this step, the capture is aimed at nothing. +In the README's documented GSM-850 scan, `kal -s GSM850` surfaces several live ARFCNs and the strongest reading is `chan: 145 (872.6MHz - 7Hz) power: 33605.48` [kalibrate]. Re-running `kal -c 145` on that carrier averages the FCCH tone into a tight clock offset, `average -1Hz [-8, 7] (range 14, stddev 3.948722)` with `overruns: 0` and `not found: 0`, a clean lock to carry forward (current kalibrate-rtl builds print the equivalent trailing line as an `average absolute error: %.3f ppm` figure, per `src/offset.cc`) [kalibrate]. Tuning gqrx to that centre would confirm a steady 200 kHz downlink picket. Carried forward into the capture step, `grgsm_livemon -f 872.6M` on the same ARFCN (with the measured offset) demodulates the BCCH and streams GSMTAP into Wireshark, at which point the Oros42 IMSI-catcher reads the GSMTAP feed and prints the IMSI/TMSI the cell pages, with no transmit [grgsm][imsicatcher]. The carrier survey is the prerequisite: without the ARFCN, power and offset from this step, the capture is aimed at nothing. ## Remediation -This is an environmental baseline and target-selection step, not a device defect — the "weakness" it surfaces (a continuously-broadcast, unauthenticated carrier whose synchronisation bursts advertise the cell) is inherent to GSM's air-interface design [ts45002][dabrowski2014]. Layered guidance for what can be hardened around it: +This is an environmental baseline and target-selection step, not a device defect, the "weakness" it surfaces (a continuously-broadcast, unauthenticated carrier whose synchronisation bursts advertise the cell) is inherent to GSM's air-interface design [ts45002][dabrowski2014]. Layered guidance for what can be hardened around it: -- **Network operator** — you cannot hide the BCCH carrier or its FCCH/SCH bursts, but you can limit what the *post-survey* capture yields: page by TMSI rather than IMSI and minimise IMSI exposure during location update, run the strongest available ciphering (A5/3, not A5/1), and monitor for anomalous carriers / unexpected ARFCNs that signal a fake cell mimicking your network [dabrowski2014]. Where possible, retire 2G or gate downgrade from 4G/5G, since legacy GSM is what makes this survey-then-capture chain reachable. +- **Network operator**, you cannot hide the BCCH carrier or its FCCH/SCH bursts, but you can limit what the *post-survey* capture yields: page by TMSI rather than IMSI and minimise IMSI exposure during location update, run the strongest available ciphering (A5/3, not A5/1), and monitor for anomalous carriers / unexpected ARFCNs that signal a fake cell mimicking your network [dabrowski2014]. Where possible, retire 2G or gate downgrade from 4G/5G, since legacy GSM is what makes this survey-then-capture chain reachable. -- **Device integrator** — select basebands that resist silent downgrade to GSM and that surface 2G/rogue-cell indicators to the user; a device that never falls back to an unauthenticated GSM carrier removes itself from the population this survey targets [dabrowski2014]. +- **Device integrator**, select basebands that resist silent downgrade to GSM and that surface 2G/rogue-cell indicators to the user; a device that never falls back to an unauthenticated GSM carrier removes itself from the population this survey targets [dabrowski2014]. -- **Auditor / operator of the test** — keep this step strictly receive-only; do not transmit on licensed cellular spectrum. Treat the band/ARFCN/power/ppm inventory as scoping data, confirm each target carrier is inside your receiver's tuning envelope before committing capture hardware (RFSAM-RES-01), and conduct any identity-harvesting or active follow-on (rogue cell, decrypt) only on your own equipment with test SIMs, RF shielding and explicit written permission [dabrowski2014]. +- **Auditor / operator of the test**, keep this step strictly receive-only; do not transmit on licensed cellular spectrum. Treat the band/ARFCN/power/ppm inventory as scoping data, confirm each target carrier is inside your receiver's tuning envelope before committing capture hardware (RFSAM-RES-01), and conduct any identity-harvesting or active follow-on (rogue cell, decrypt) only on your own equipment with test SIMs, RF shielding and explicit written permission [dabrowski2014]. diff --git a/src/content/controls/rfsam-lora-cr-01.md b/src/content/controls/rfsam-lora-cr-01.md index a6108bf..66ed47d 100644 --- a/src/content/controls/rfsam-lora-cr-01.md +++ b/src/content/controls/rfsam-lora-cr-01.md @@ -9,27 +9,27 @@ applicability: deferred: false objective: >- Determine whether a LoRaWAN deployment's join procedure and key management are - sound — that the root AppKey is a per-device random value (not default, shared + sound, that the root AppKey is a per-device random value (not default, shared or guessable), that DevNonce is fresh per join, and that session keys are not - static and reused — by analysing captured join and data frames against the + static and reused, by analysing captured join and data frames against the network's stated LoRaWAN version and activation mode. intro: >- LoRaWAN's entire confidentiality and integrity model hangs off the root key: the AppKey (1.0.x) or NwkKey+AppKey (1.1) from which every session key is - derived. There is no feasible brute force of a strong random AES-128 key — the + derived. There is no feasible brute force of a strong random AES-128 key, the exposure is in how keys and nonces are managed. This control checks the join and session-key chain for default/shared keys, DevNonce reuse, and static ABP session keys, the recurring real-world failures that collapse the crypto. prerequisites: hardware: - 'An SDR covering the regional sub-GHz band (RTL-SDR V4 for one channel, or HackRF One / USRP B210 / bladeRF 2.0 micro for wider capture), or a multi-channel LoRaWAN gateway (RAK WisGate Connect) if you have gateway access' - - 'A host to run the offline key/MIC analysis (no transmit hardware needed — this control is analysis over an existing capture)' + - 'A host to run the offline key/MIC analysis (no transmit hardware needed, this control is analysis over an existing capture)' software: - 'A CSS demodulator that frames LoRaWAN and exports LoRaTap PCAP (gr-lora_sdr, LoRAttack) plus Wireshark, then an offline LoRaWAN crypto toolkit: Loracrack (weak/shared AppKey → session-key derivation) and/or LAF (MIC recompute/validate, key-candidate testing)' signal: - freq: '863–870 MHz (EU868) / 902–928 MHz (US915) / regional: AS923, EU433, AU915, CN470, IN865, KR920' + freq: '863 to 870 MHz (EU868) / 902 to 928 MHz (US915) / regional: AS923, EU433, AU915, CN470, IN865, KR920' bandwidth: '125 / 250 / 500 kHz per LoRaWAN channel' - modulation: 'CSS (Chirp Spread Spectrum), SF7–SF12' + modulation: 'CSS (Chirp Spread Spectrum), SF7 to SF12' skill: advanced attacks: - name: Default / shared / hardcoded AppKey recovery @@ -39,7 +39,7 @@ attacks: impact: >- Recovering or guessing the root AppKey lets an attacker derive both session keys (NwkSKey, AppSKey) for every session, decrypt all application traffic, - and forge frames with valid MICs — a full break of the device's crypto. + and forge frames with valid MICs, a full break of the device's crypto. preconditions: >- The device uses a default, shared, vendor-wide or otherwise guessable AppKey, or one extractable from firmware / public source; plus a captured @@ -60,7 +60,7 @@ attacks: JoinRequests, forcing rejoin/desynchronisation or denial of service, and indicates a join-security model that does not reject stale nonces. preconditions: >- - A LoRaWAN 1.0.0–1.0.3 device whose DevNonce is a random value (birthday + A LoRaWAN 1.0.0 to 1.0.3 device whose DevNonce is a random value (birthday collision over device lifetime) or reused after reboot/poor RNG; the join is cleartext, so the DevNonce sequence is observable passively. summary: >- @@ -80,7 +80,7 @@ attacks: frame counter resets on power-cycle, captured passively. summary: >- ABP trades key rotation for simplicity: static session keys plus a - resettable frame counter give keystream reuse and replay — the + resettable frame counter give keystream reuse and replay, the session-key-management failure OTAA is designed to avoid. references: - key: hessel2022survey @@ -100,7 +100,7 @@ references: - key: na2017replay title: Scenario and countermeasure for replay attack using join request messages in LoRaWAN authors: 'S. H. Na, D. Hwang, W. Shin, K.-H. Kim' - venue: 'IEEE ICOIN 2017, pp. 718–720' + venue: 'IEEE ICOIN 2017, pp. 718 to 720' year: 2017 url: 'https://ieeexplore.ieee.org/document/7899580/' type: paper @@ -112,7 +112,7 @@ references: url: 'https://www.tarlogic.com/blog/lorawan-vulnerabilities-versions/' type: blog - key: loraalliance2020joinsync - title: 'LoRaWAN 1.0.x Join-Synch Issues — Remedies (v1.0.0)' + title: 'LoRaWAN 1.0.x Join-Synch Issues, Remedies (v1.0.0)' authors: LoRa Alliance Technical Committee venue: LoRa Alliance year: 2020 @@ -126,20 +126,20 @@ references: url: 'https://lora-alliance.org/wp-content/uploads/2021/11/LoRaWAN-Link-Layer-Specification-v1.0.4.pdf' type: standard - key: loracrack - title: 'Loracrack — LoRaWAN session cracker (PoC for weak/shared Application Keys)' + title: 'Loracrack, LoRaWAN session cracker (PoC for weak/shared Application Keys)' authors: 'S. Mellema (Applied Risk)' venue: GitHub year: 2022 url: 'https://github.com/applied-risk/Loracrack' type: tool - key: laf - title: 'LAF — LoRaWAN Auditing Framework' + title: 'LAF, LoRaWAN Auditing Framework' authors: IOActive venue: GitHub url: 'https://github.com/IOActive/laf' type: tool - key: lorapacket - title: 'lora-packet — LoRaWAN packet decoder/encoder (test vectors + README walkthrough)' + title: 'lora-packet, LoRaWAN packet decoder/encoder (test vectors + README walkthrough)' authors: A. Kirby venue: GitHub url: 'https://github.com/anthonykirby/lora-packet' @@ -160,11 +160,11 @@ lastResearched: 2026-06-14 LoRaWAN's confidentiality and integrity derive entirely from a root key, so this layer is about key and nonce *management*, not cipher strength. In 1.0.x the device and back end share an AppKey; in 1.1 the root is split into NwkKey and AppKey. From the root, the two session keys are derived: the `AppSKey` encrypts the `FRMPayload` (AES-128), and the `NwkSKey` keys the 4-byte MIC (AES-128-CMAC) [loraalliance2020l2][hessel2022survey]. There is no feasible brute force of a strong random AES-128 root key; the real-world exposure is that the key is often not strong, not unique, or not secret, and that the join nonce and session keys are mismanaged [hessel2022survey]. -**Default / shared / hardcoded AppKey.** IOActive's audit of real LoRaWAN deployments found root keys that were hardcoded in firmware, shared fleet-wide, set to vendor defaults, or otherwise easy to source from public repositories or weak enough to guess [ioactive2020lorawan]. Because every session key descends from that root, recovering it once decrypts all traffic for the device's lifetime and lets an attacker forge frames with valid MICs — a complete crypto break [ioactive2020lorawan][hessel2022survey]. This is exactly what a candidate-key test demonstrates: given a guessed/leaked AppKey and a captured join, derive the session keys and confirm by recomputing the captured MIC [loracrack][laf]. It is *not* a brute force of a strong key [loracrack]. +**Default / shared / hardcoded AppKey.** IOActive's audit of real LoRaWAN deployments found root keys that were hardcoded in firmware, shared fleet-wide, set to vendor defaults, or otherwise easy to source from public repositories or weak enough to guess [ioactive2020lorawan]. Because every session key descends from that root, recovering it once decrypts all traffic for the device's lifetime and lets an attacker forge frames with valid MICs, a complete crypto break [ioactive2020lorawan][hessel2022survey]. This is exactly what a candidate-key test demonstrates: given a guessed/leaked AppKey and a captured join, derive the session keys and confirm by recomputing the captured MIC [loracrack][laf]. It is *not* a brute force of a strong key [loracrack]. -**DevNonce reuse / join replay (1.0.x).** The OTAA `JoinRequest` carries `JoinEUI`/`AppEUI`, `DevEUI` and a `DevNonce` in the clear, protected only by a MIC — the key is never transmitted, but the DevNonce sequence is fully observable passively [loraalliance2020l2]. In LoRaWAN 1.0.0–1.0.3 the DevNonce is a *random* value, and the network must remember and reject previously-seen values; a repeat lets a captured JoinRequest be replayed [na2017replay][loraalliance2020joinsync]. Reuse is not hypothetical: the random nonce is subject to the birthday paradox over a multi-year lifetime, and constrained devices reuse nonces after reboots, counter resets, or poor RNG seeding [hessel2022survey]. LoRaWAN 1.0.4 and 1.1 redefine DevNonce as a monotonic counter that SHALL never be reused for a given JoinEUI, closing this window — at the cost of the join-synchronisation problems the LoRa Alliance documents for mixed fleets [loraalliance2020joinsync][loraalliance2020l2]. +**DevNonce reuse / join replay (1.0.x).** The OTAA `JoinRequest` carries `JoinEUI`/`AppEUI`, `DevEUI` and a `DevNonce` in the clear, protected only by a MIC, the key is never transmitted, but the DevNonce sequence is fully observable passively [loraalliance2020l2]. In LoRaWAN 1.0.0 to 1.0.3 the DevNonce is a *random* value, and the network must remember and reject previously-seen values; a repeat lets a captured JoinRequest be replayed [na2017replay][loraalliance2020joinsync]. Reuse is not hypothetical: the random nonce is subject to the birthday paradox over a multi-year lifetime, and constrained devices reuse nonces after reboots, counter resets, or poor RNG seeding [hessel2022survey]. LoRaWAN 1.0.4 and 1.1 redefine DevNonce as a monotonic counter that SHALL never be reused for a given JoinEUI, closing this window, at the cost of the join-synchronisation problems the LoRa Alliance documents for mixed fleets [loraalliance2020joinsync][loraalliance2020l2]. -**Static ABP session keys / frame-counter reset.** ABP (Activation By Personalisation) burns static `NwkSKey`/`AppSKey`/`DevAddr` into the device with no per-join rotation. If the frame counter resets on power-cycle, the AES-CTR-style payload encryption repeats keystream (a two-time pad recoverable by XOR) and stale frames become replayable — both reachable without ever recovering the key [hessel2022survey][tarlogic2020lorawan]. OTAA exists precisely to avoid this by deriving fresh session keys at each join. +**Static ABP session keys / frame-counter reset.** ABP (Activation By Personalisation) burns static `NwkSKey`/`AppSKey`/`DevAddr` into the device with no per-join rotation. If the frame counter resets on power-cycle, the AES-CTR-style payload encryption repeats keystream (a two-time pad recoverable by XOR) and stale frames become replayable, both reachable without ever recovering the key [hessel2022survey][tarlogic2020lorawan]. OTAA exists precisely to avoid this by deriving fresh session keys at each join. The IOActive findings (default/hardcoded/weak AppKeys) are reported across audited deployments and firmware, not a single named CVE; treat them as a representative pattern and check the specific device/stack before asserting a given deployment is affected. Loracrack and LAF are PoC/audit tooling (Loracrack last pushed 2022-06, LAF 2023-05); re-confirm they build against your capture format and LoRaWAN version before relying on them. @@ -176,7 +176,7 @@ The IOActive findings (default/hardcoded/weak AppKeys) are reported across audit > is offline analysis over a capture you are authorised to hold. Test AppKey > candidates only against your own / in-scope devices. -1. **Capture the join and following data frames** for the target device, per RFSAM-RES-07 and RFSAM-LORA-LL-01 — de-chirp the CSS waveform and export a LoRaTap PCAP that contains at least one OTAA `JoinRequest`/`JoinAccept` pair and subsequent uplinks for the same `DevAddr`. Confirm in Wireshark: +1. **Capture the join and following data frames** for the target device, per RFSAM-RES-07 and RFSAM-LORA-LL-01, de-chirp the CSS waveform and export a LoRaTap PCAP that contains at least one OTAA `JoinRequest`/`JoinAccept` pair and subsequent uplinks for the same `DevAddr`. Confirm in Wireshark: ```text lorawan.mtype == 0 # Join Request: JoinEUI/AppEUI, DevEUI, DevNonce (cleartext) lorawan.mtype == 1 # Join Accept (encrypted) @@ -198,11 +198,11 @@ The IOActive findings (default/hardcoded/weak AppKeys) are reported across audit # Loracrack: derive session keys from a candidate AppKey and validate via the MIC python loracrack.py --pcap capture.pcap --appkey ``` - Expected: for the *correct* key, the tool derives `NwkSKey`/`AppSKey` and the recomputed MIC matches the captured frame's MIC — confirming the key and that the session is now decryptable [loracrack]. For a wrong key the MIC mismatches. Equivalently, use LAF to recompute and validate the MIC against a key candidate [laf]. A match is a finding: the root key is not secret. + Expected: for the *correct* key, the tool derives `NwkSKey`/`AppSKey` and the recomputed MIC matches the captured frame's MIC, confirming the key and that the session is now decryptable [loracrack]. For a wrong key the MIC mismatches. Equivalently, use LAF to recompute and validate the MIC against a key candidate [laf]. A match is a finding: the root key is not secret. > A MIC match means you have recovered the session keys for that capture. Decrypt only traffic you are authorised to analyse; do not act on recovered keys beyond the agreed scope. -5. **Audit ABP session-key hygiene (ABP).** For ABP devices, confirm whether the frame counter (`FCnt`) ever resets — capture across a device reboot/power-cycle in your test rig and check for a counter that returns to a low value while the `DevAddr` and (static) keys are unchanged: +5. **Audit ABP session-key hygiene (ABP).** For ABP devices, confirm whether the frame counter (`FCnt`) ever resets, capture across a device reboot/power-cycle in your test rig and check for a counter that returns to a low value while the `DevAddr` and (static) keys are unchanged: ```text lorawan.dev_addr == # then read the FCnt column over time ``` @@ -212,9 +212,9 @@ The IOActive findings (default/hardcoded/weak AppKeys) are reported across audit ## Field case -Reported measurement (carried over from the paired link-layer control). The same authorised US915 capture used to profile this network at the link layer (RFSAM-LORA-LL-01) — 51,304 LoRaWAN frames, of which 45,815 (89.3%) were JoinRequests — is the input for the CR-layer key analysis: because the capture was so heavily dominated by JoinRequests, each device's DevNonce sequence was directly observable in the clear, which is the prerequisite for spotting reuse [loraalliance2020joinsync]. The application payloads stayed AES-128 protected throughout — confidentiality held against the *capture*; the question this control asks is whether it holds against the *key management*. This frame/JoinRequest count is the author's reported field figure, reproduced verbatim from the paired RFSAM-LORA-LL-01 control; it has not been independently re-measured here. +Reported measurement (carried over from the paired link-layer control). The same authorised US915 capture used to profile this network at the link layer (RFSAM-LORA-LL-01), 51,304 LoRaWAN frames, of which 45,815 (89.3%) were JoinRequests, is the input for the CR-layer key analysis: because the capture was so heavily dominated by JoinRequests, each device's DevNonce sequence was directly observable in the clear, which is the prerequisite for spotting reuse [loraalliance2020joinsync]. The application payloads stayed AES-128 protected throughout, confidentiality held against the *capture*; the question this control asks is whether it holds against the *key management*. This frame/JoinRequest count is the author's reported field figure, reproduced verbatim from the paired RFSAM-LORA-LL-01 control; it has not been independently re-measured here. -Illustrative walkthrough — substitute the values you capture. To reproduce against your own authorised test network: stand up a couple of OTAA devices and one ABP device on a ChirpStack/RAK gateway, deliberately provision one OTAA device with a default/sample AppKey (so the key-candidate test in step 4 succeeds), and one 1.0.x device that re-joins on reboot (so step 3 shows a DevNonce repeat). Then run steps 3–5 and tabulate: +Illustrative walkthrough, substitute the values you capture. To reproduce against your own authorised test network: stand up a couple of OTAA devices and one ABP device on a ChirpStack/RAK gateway, deliberately provision one OTAA device with a default/sample AppKey (so the key-candidate test in step 4 succeeds), and one 1.0.x device that re-joins on reboot (so step 3 shows a DevNonce repeat). Then run steps 3 to 5 and tabulate: ```text # per-device key-management findings from an authorised test capture @@ -224,14 +224,14 @@ DevEUI / DevAddr version activation DevNonce AppKey test A [FILL: id] 1.0.3 ABP n/a n/a [FILL: y/n] ``` -Reproducible public worked example (no live capture) for the step-4 cell. Rather than depend on a live measurement, the candidate-key/MIC test for the weak OTAA row above is grounded in a documented public test vector shipped with the `lora-packet` library [lorapacket]. For the data uplink frame `40F17DBE4900020001954378762B11FF0D`, feeding the candidate NwkSKey `44024241ed4ce9a68c6a8bc055233fd3` recomputes the MIC as `2b11ff0d`, which equals the frame's trailing MIC bytes — `verifyMIC` returns true (`MIC check=OK`) — and feeding the AppSKey `ec925802ae430ca77fd3dd73cb2cc588` decrypts the `FRMPayload` to the ASCII plaintext `test`. The same library's vectors also confirm the join side: for the JoinRequest `0039363463336913AA05693574323831330489C65B1304`, the candidate AppKey `98929b92c49edba9676d646d3b612456` recomputes the JoinRequest MIC as `c65b1304`, again matching the frame. These values are self-consistent and reproducible entirely offline (`__tests__/mic_test.ts`, `__tests__/decrypt_test.ts`, and the README CLI decoder walkthrough), so the "candidate key → MIC match → decryptable payload" chain of step 4 can be demonstrated end-to-end without any live RF capture [lorapacket]. +Reproducible public worked example (no live capture) for the step-4 cell. Rather than depend on a live measurement, the candidate-key/MIC test for the weak OTAA row above is grounded in a documented public test vector shipped with the `lora-packet` library [lorapacket]. For the data uplink frame `40F17DBE4900020001954378762B11FF0D`, feeding the candidate NwkSKey `44024241ed4ce9a68c6a8bc055233fd3` recomputes the MIC as `2b11ff0d`, which equals the frame's trailing MIC bytes, `verifyMIC` returns true (`MIC check=OK`), and feeding the AppSKey `ec925802ae430ca77fd3dd73cb2cc588` decrypts the `FRMPayload` to the ASCII plaintext `test`. The same library's vectors also confirm the join side: for the JoinRequest `0039363463336913AA05693574323831330489C65B1304`, the candidate AppKey `98929b92c49edba9676d646d3b612456` recomputes the JoinRequest MIC as `c65b1304`, again matching the frame. These values are self-consistent and reproducible entirely offline (`__tests__/mic_test.ts`, `__tests__/decrypt_test.ts`, and the README CLI decoder walkthrough), so the "candidate key → MIC match → decryptable payload" chain of step 4 can be demonstrated end-to-end without any live RF capture [lorapacket]. -The expected shape: the deliberately weak OTAA device yields a MIC match under the default key (its session keys are recoverable and traffic decryptable, exactly as the `lora-packet` vector above shows), the 1.0.x re-joining device shows a repeated DevNonce (join-replay exposure), and the ABP device's counter resets across reboot (keystream-reuse/replay exposure) — while a correctly provisioned 1.1 OTAA device passes all three. The remaining `[FILL: …]` cells above are placeholders for the values you capture in your own authorised analysis — they are not measured findings. +The expected shape: the deliberately weak OTAA device yields a MIC match under the default key (its session keys are recoverable and traffic decryptable, exactly as the `lora-packet` vector above shows), the 1.0.x re-joining device shows a repeated DevNonce (join-replay exposure), and the ABP device's counter resets across reboot (keystream-reuse/replay exposure), while a correctly provisioned 1.1 OTAA device passes all three. The remaining `[FILL: …]` cells above are placeholders for the values you capture in your own authorised analysis, they are not measured findings. ## Remediation **Developer (device / stack).** Provision a unique, cryptographically random AppKey (1.0.x) or NwkKey+AppKey (1.1) per device; never ship a default, sample, all-zero, fleet-wide or firmware-hardcoded root key, since recovering it once breaks every session for the device's life [ioactive2020lorawan][hessel2022survey]. Generate DevNonce correctly: on 1.0.4/1.1 use the mandated monotonic counter that is never reused for a JoinEUI and persists across reboots; on legacy 1.0.x with a random DevNonce, ensure adequate RNG entropy and persistence so nonces do not repeat after a reset [loraalliance2020l2][loraalliance2020joinsync]. Prefer OTAA over ABP so session keys are derived fresh at each join rather than burned in static. -**Integrator (network / join server).** Enforce strict server-side DevNonce tracking: remember and reject previously-seen DevNonce values (1.0.x) or enforce monotonicity (1.0.4/1.1), so a replayed JoinRequest is denied [na2017replay][loraalliance2020joinsync]. For ABP deployments, enforce frame-counter validation that survives device reboots — reject a counter that resets rather than accepting it — to neutralise the keystream-reuse and replay paths [hessel2022survey][tarlogic2020lorawan]. Where feasible, migrate to 1.1's split keys and Join Server, and ensure no 1.0.x elements remain in a network claimed to be 1.1, since backward compatibility reopens the older weaknesses [tarlogic2020lorawan]. +**Integrator (network / join server).** Enforce strict server-side DevNonce tracking: remember and reject previously-seen DevNonce values (1.0.x) or enforce monotonicity (1.0.4/1.1), so a replayed JoinRequest is denied [na2017replay][loraalliance2020joinsync]. For ABP deployments, enforce frame-counter validation that survives device reboots, reject a counter that resets rather than accepting it, to neutralise the keystream-reuse and replay paths [hessel2022survey][tarlogic2020lorawan]. Where feasible, migrate to 1.1's split keys and Join Server, and ensure no 1.0.x elements remain in a network claimed to be 1.1, since backward compatibility reopens the older weaknesses [tarlogic2020lorawan]. -**Operator (deployment).** Treat the root key as the crown jewel: rotate keys where the lifecycle allows, audit that every deployed device carries a unique key (not a shared batch value), and protect the network/join server credentials so the keys cannot be read from an exposed back end [ioactive2020lorawan]. Periodically run this passive join/session-key audit against your own network as a monitoring control — a recurring DevNonce, a successful default-key derivation, or a resetting ABP counter is a provisioning failure to fix, not merely an attacker's opportunity. +**Operator (deployment).** Treat the root key as the crown jewel: rotate keys where the lifecycle allows, audit that every deployed device carries a unique key (not a shared batch value), and protect the network/join server credentials so the keys cannot be read from an exposed back end [ioactive2020lorawan]. Periodically run this passive join/session-key audit against your own network as a monitoring control, a recurring DevNonce, a successful default-key derivation, or a resetting ABP counter is a provisioning failure to fix, not merely an attacker's opportunity. diff --git a/src/content/controls/rfsam-lora-ll-01.md b/src/content/controls/rfsam-lora-ll-01.md index ebe676e..da81c0c 100644 --- a/src/content/controls/rfsam-lora-ll-01.md +++ b/src/content/controls/rfsam-lora-ll-01.md @@ -8,9 +8,9 @@ applicability: - LoRaWAN deferred: false objective: >- - Verify whether a LoRaWAN deployment can be inventoried passively — classifying + Verify whether a LoRaWAN deployment can be inventoried passively, classifying frames by MType and harvesting the cleartext join-procedure identifiers - (JoinEUI/AppEUI, DevEUI, DevNonce) and the data-frame DevAddr — without + (JoinEUI/AppEUI, DevEUI, DevNonce) and the data-frame DevAddr, without transmitting, and use the frame mix to scope downstream weaknesses. intro: >- LoRaWAN encrypts the application payload (AES-128) but transmits the @@ -22,11 +22,11 @@ prerequisites: hardware: - 'An SDR covering the regional sub-GHz band (RTL-SDR V4 for one channel, or HackRF One / USRP B210 / bladeRF 2.0 micro for wider capture), or a multi-channel LoRaWAN gateway (RAK WisGate Connect) if you have gateway access, or an STM32WLxx board for single-board capture' software: - - 'A CSS demodulator that frames LoRaWAN and exports LoRaTap PCAP — gr-lora_sdr, LoRAttack, ChirpCat (gateway), catnip (CatSniffer), or the LoRa Wideband Decoder — plus Wireshark with its LoRaTap/LoRaWAN dissectors' + - 'A CSS demodulator that frames LoRaWAN and exports LoRaTap PCAP, gr-lora_sdr, LoRAttack, ChirpCat (gateway), catnip (CatSniffer), or the LoRa Wideband Decoder, plus Wireshark with its LoRaTap/LoRaWAN dissectors' signal: - freq: '863–870 MHz (EU868) / 902–928 MHz (US915) / regional: AS923, EU433, AU915, CN470, IN865, KR920' + freq: '863 to 870 MHz (EU868) / 902 to 928 MHz (US915) / regional: AS923, EU433, AU915, CN470, IN865, KR920' bandwidth: '125 / 250 / 500 kHz per LoRaWAN channel' - modulation: 'CSS (Chirp Spread Spectrum), SF7–SF12' + modulation: 'CSS (Chirp Spread Spectrum), SF7 to SF12' skill: intermediate attacks: - name: ABP replay / selective denial-of-service @@ -42,7 +42,7 @@ attacks: cleartext header harvested here identifies replayable targets. summary: >- Long-term ABP session keys outlive a single session, so a frame replayed - after a counter reset is accepted — a selective DoS scoped by the + after a counter reset is accepted, a selective DoS scoped by the passively harvested frame headers. - name: Plaintext recovery via keystream reuse refs: @@ -79,14 +79,14 @@ references: - key: yang2018lorawan title: Security Vulnerabilities in LoRaWAN authors: 'X. Yang, E. Karampatzakis, C. Doerr, F. Kuipers' - venue: 'IEEE/ACM IoTDI 2018, pp. 129–140' + venue: 'IEEE/ACM IoTDI 2018, pp. 129 to 140' year: 2018 url: 'https://ieeexplore.ieee.org/document/8366983/' type: paper - key: lee2017bitflip title: Risk analysis and countermeasure for bit-flipping attack in LoRaWAN authors: 'J. Lee, D. Hwang, J. Park, K.-H. Kim' - venue: 'IEEE ICOIN 2017, pp. 549–551' + venue: 'IEEE ICOIN 2017, pp. 549 to 551' year: 2017 url: 'https://ieeexplore.ieee.org/document/7899554/' type: paper @@ -105,19 +105,19 @@ references: url: 'https://lora-alliance.org/wp-content/uploads/2021/11/LoRaWAN-Link-Layer-Specification-v1.0.4.pdf' type: standard - key: loratap - title: 'LINKTYPE_LORATAP — LoRaTap pcap link-layer header' + title: 'LINKTYPE_LORATAP, LoRaTap pcap link-layer header' authors: 'E. de Jong (eriknl), tcpdump.org' venue: tcpdump / libpcap url: 'https://www.tcpdump.org/linktypes/LINKTYPE_LORATAP.html' type: spec - key: grlorasdr - title: 'gr-lora_sdr — GNU Radio SDR implementation of a LoRa transceiver' + title: 'gr-lora_sdr, GNU Radio SDR implementation of a LoRa transceiver' authors: 'J. Tapparel et al., EPFL TCL' venue: GitHub url: 'https://github.com/tapparelj/gr-lora_sdr' type: tool - key: lorattackrepo - title: 'LoRAttack — toolkit for assessing LoRaWAN network security' + title: 'LoRAttack, toolkit for assessing LoRaWAN network security' authors: konicst1 venue: GitHub url: 'https://github.com/konicst1/lorattack' @@ -139,26 +139,26 @@ lastResearched: 2026-06-14 ## Mechanism -LoRaWAN is a MAC/network layer carried over the LoRa CSS PHY. The over-the-air unit is the `PHYPayload = MHDR | MACPayload | MIC(4B)`; the `MHDR` carries the message type (`MType`), and the `MACPayload` carries an `FHDR` (`DevAddr`, `FCtrl`, `FCnt`, `FOpts`), an `FPort`, and the `FRMPayload` [loraalliance2020l2]. Only the `FRMPayload` is encrypted (AES-128 under the AppSKey); the headers — including the stable `DevAddr` — travel in the clear, and the MIC is an AES-128-CMAC keyed by the NwkSKey rather than an encryption layer [loraalliance2020l2]. +LoRaWAN is a MAC/network layer carried over the LoRa CSS PHY. The over-the-air unit is the `PHYPayload = MHDR | MACPayload | MIC(4B)`; the `MHDR` carries the message type (`MType`), and the `MACPayload` carries an `FHDR` (`DevAddr`, `FCtrl`, `FCnt`, `FOpts`), an `FPort`, and the `FRMPayload` [loraalliance2020l2]. Only the `FRMPayload` is encrypted (AES-128 under the AppSKey); the headers, including the stable `DevAddr`, travel in the clear, and the MIC is an AES-128-CMAC keyed by the NwkSKey rather than an encryption layer [loraalliance2020l2]. -The join procedure is even more exposed. In OTAA, the `JoinRequest` carries `JoinEUI`/`AppEUI`, `DevEUI`, and a `DevNonce` **before any session key exists**; these fields are sent in the clear and protected only by a MIC computed with the AppKey, so the key is never transmitted but the identifiers are fully readable [loraalliance2020l2]. A passive receiver that has de-chirped the waveform into frames can therefore classify traffic by `MType` (Join Request, Join Accept, Unconfirmed/Confirmed Data Up/Down) and inventory a whole deployment — which devices exist, which are joining, how often — and harvest fleet-wide identifiers, all without transmitting. +The join procedure is even more exposed. In OTAA, the `JoinRequest` carries `JoinEUI`/`AppEUI`, `DevEUI`, and a `DevNonce` **before any session key exists**; these fields are sent in the clear and protected only by a MIC computed with the AppKey, so the key is never transmitted but the identifiers are fully readable [loraalliance2020l2]. A passive receiver that has de-chirped the waveform into frames can therefore classify traffic by `MType` (Join Request, Join Accept, Unconfirmed/Confirmed Data Up/Down) and inventory a whole deployment, which devices exist, which are joining, how often, and harvest fleet-wide identifiers, all without transmitting. This passive frame profile is the scoping step for the documented LoRaWAN attack families, which this control does not itself execute: - **ABP replay / selective DoS.** Yang et al. show that because ABP session keys are long-term and outlive a single session, an uplink replayed after a device's frame counter resets is accepted, causing a selective denial-of-service or desynchronisation [yang2018lorawan]. The cleartext `DevAddr` and `FCnt` harvested here identify which devices are replayable. -- **Plaintext recovery by keystream reuse.** The same work demonstrates that the AES-CTR-style payload encryption reuses keystream when the frame counter repeats under a static key, so XORing two such ciphertexts recovers plaintext — a classic two-time pad reachable from passive capture alone [yang2018lorawan]. +- **Plaintext recovery by keystream reuse.** The same work demonstrates that the AES-CTR-style payload encryption reuses keystream when the frame counter repeats under a static key, so XORing two such ciphertexts recovers plaintext, a classic two-time pad reachable from passive capture alone [yang2018lorawan]. - **Bit-flipping on the backend leg.** The MIC protects the device-to-network-server hop, but the payload the network server decrypts and forwards to the application server is no longer cryptographically bound; Lee et al. analyse the resulting bit-flipping risk and propose a field-shuffling countermeasure [lee2017bitflip], and Trend Micro independently note the same unprotected NS→AS leg and recommend an application-layer MIC or a TLS tunnel [trendmicro2021lorawan]. This attack targets the network-server-to-application-server backend interface, not the RF link: passive capture here only scopes which fields are exposed, so verify the backend topology before asserting exploitability for a given deployment. A high proportion of `JoinRequest` frames relative to data frames is itself a finding: it indicates devices repeatedly failing to join (lost downlinks, poor coverage, mis-provisioned keys), so the network is in effect broadcasting its own poor health and offering more cleartext identifiers to harvest. ## Procedure -> Authorised testing only — capture is passive, but confirm you have written +> Authorised testing only, capture is passive, but confirm you have written > permission to receive and analyse the target network's traffic and that > passive RF interception is lawful in your jurisdiction. Do not transmit at > this layer. -1. **Confirm the band and channel plan** (from RFSAM-RES-07 / the IG and SP steps). Set the regional sub-band you will capture — e.g. EU868 (863–870 MHz) or US915 (902–928 MHz) — and the bandwidth (125/250/500 kHz) and spreading factor (SF7–SF12) in play. +1. **Confirm the band and channel plan** (from RFSAM-RES-07 / the IG and SP steps). Set the regional sub-band you will capture, e.g. EU868 (863 to 870 MHz) or US915 (902 to 928 MHz), and the bandwidth (125/250/500 kHz) and spreading factor (SF7 to SF12) in play. 2. **De-chirp the CSS waveform into LoRaWAN frames.** With an SDR, run a soft-decision LoRa receiver such as gr-lora_sdr [grlorasdr], which provides sync, timing and frequency-offset correction down to low SNR. Its example decoders take the centre frequency, bandwidth and spreading factor and emit decoded frames: ```bash @@ -171,9 +171,9 @@ A high proportion of `JoinRequest` frames relative to data frames is itself a fi ```bash ./run.sh # menu: "Sniff Up/Down link (Bidirectional)" ``` - Expected: a PCAP per session under the tool's capture directory. The `*_wireshark` PCAPs have the UDP header stripped and the DLT set for Wireshark. (Author notes the sniffer is tested mainly at 125 kHz and is under active construction — verify against your band/SF.) + Expected: a PCAP per session under the tool's capture directory. The `*_wireshark` PCAPs have the UDP header stripped and the DLT set for Wireshark. (Author notes the sniffer is tested mainly at 125 kHz and is under active construction, verify against your band/SF.) -4. **Or, with gateway access**, read whole uplink+downlink frames off a concentrator with ChirpCat (RAK WisGate Connect, Semtech UDP packet forwarder), or capture the whole sub-band at once with the LoRa Wideband Decoder, or use catnip on a CatSniffer SX1262 for single-radio capture — each captures LoRaWAN frames without an SDR de-chirp flow. +4. **Or, with gateway access**, read whole uplink+downlink frames off a concentrator with ChirpCat (RAK WisGate Connect, Semtech UDP packet forwarder), or capture the whole sub-band at once with the LoRa Wideband Decoder, or use catnip on a CatSniffer SX1262 for single-radio capture, each captures LoRaWAN frames without an SDR de-chirp flow. 5. **Dissect in Wireshark.** Open the LoRaTap PCAP; Wireshark's `loratap`/`lorawan` dissectors decode the `PHYPayload` [loratap]. The LoRaWAN dissector registers under LoRaTap and parses the `MHDR`/`MType`, `FHDR` (`DevAddr`, `FCtrl`, `FCnt`), and the join fields. Filter and classify: ```text @@ -187,7 +187,7 @@ A high proportion of `JoinRequest` frames relative to data frames is itself a fi ## Field case -Reported field observation (the author's own measurement on an authorised network, reproduced here as an illustrative figure — not independently re-measured for this control): a passive US915 capture of 51,304 LoRaWAN frames showed 45,815 (89.3%) were JoinRequests — nine of every ten frames were devices trying, and failing, to join. The structure read entirely in the clear (MHDR + DevAddr; AppEUI/DevEUI/DevNonce in the join), letting an observer harvest the fleet's identities and map the network without ever transmitting. The payloads stayed AES-protected — but the metadata alone profiled the deployment and exposed it as misconfigured. (Such a JoinRequest skew is consistent with the US915 channel-plan mismatch, where a 64-channel device randomly retries joins until one lands on the gateway's active 8-channel sub-band.) +Reported field observation (the author's own measurement on an authorised network, reproduced here as an illustrative figure, not independently re-measured for this control): a passive US915 capture of 51,304 LoRaWAN frames showed 45,815 (89.3%) were JoinRequests, nine of every ten frames were devices trying, and failing, to join. The structure read entirely in the clear (MHDR + DevAddr; AppEUI/DevEUI/DevNonce in the join), letting an observer harvest the fleet's identities and map the network without ever transmitting. The payloads stayed AES-protected, but the metadata alone profiled the deployment and exposed it as misconfigured. (Such a JoinRequest skew is consistent with the US915 channel-plan mismatch, where a 64-channel device randomly retries joins until one lands on the gateway's active 8-channel sub-band.) To reproduce against your own authorised test network, stand up a couple of devices on a ChirpStack/RAK gateway, mis-provision one (wrong AppKey or a region/coverage mismatch) so it loops on join, then run the capture in step 3 and tabulate the `MType` mix: @@ -203,12 +203,12 @@ unique DevAddr seen [FILL: n] repeated DevNonce [FILL: y/n] ``` -The expected shape: a mis-provisioned fleet skews heavily toward Join Requests, in line with the reported 89.3% observation above, and every Join Request hands you a `DevEUI`/`JoinEUI`/`DevNonce` in the clear. The `[FILL: …]` rows are placeholders for the reader's own authorised capture — substitute the values you capture; do not treat them as measured values. +The expected shape: a mis-provisioned fleet skews heavily toward Join Requests, in line with the reported 89.3% observation above, and every Join Request hands you a `DevEUI`/`JoinEUI`/`DevNonce` in the clear. The `[FILL: …]` rows are placeholders for the reader's own authorised capture, substitute the values you capture; do not treat them as measured values. ## Remediation **Developer (device / stack).** Use OTAA over ABP so session keys are derived afresh at each join and the frame counter cannot trivially reset into keystream reuse [yang2018lorawan]. Target LoRaWAN 1.0.4 or 1.1, where `DevNonce` is a monotonic counter that is never reused, closing the random-nonce join-replay window [loraalliance2020l2]. Treat `DevEUI`/`JoinEUI` as non-secret identifiers (they are unavoidably on the air) but do not derive any security from their secrecy. -**Integrator (network / application server).** Add end-to-end protection across the network-server-to-application-server leg — an application-layer MIC computed with the AppSKey, or a TLS tunnel (ideally with a client certificate) — so a decrypted, forwarded payload cannot be bit-flipped undetected [lee2017bitflip][trendmicro2021lorawan]. For ABP deployments, enforce server-side frame-counter validation that survives device reboots rather than accepting a reset counter, neutralising the replay/DoS path [yang2018lorawan]. +**Integrator (network / application server).** Add end-to-end protection across the network-server-to-application-server leg, an application-layer MIC computed with the AppSKey, or a TLS tunnel (ideally with a client certificate), so a decrypted, forwarded payload cannot be bit-flipped undetected [lee2017bitflip][trendmicro2021lorawan]. For ABP deployments, enforce server-side frame-counter validation that survives device reboots rather than accepting a reset counter, neutralising the replay/DoS path [yang2018lorawan]. -**Operator (deployment).** Minimise join churn through correct provisioning and adequate downlink coverage: a deployment that constantly re-joins is leaking the maximum number of cleartext identifiers and advertising its own misconfiguration. Periodically run this passive profile against your own network as a monitoring control — a rising `JoinRequest` ratio is an early signal of provisioning or coverage failure, not just an attacker's reconnaissance aid. +**Operator (deployment).** Minimise join churn through correct provisioning and adequate downlink coverage: a deployment that constantly re-joins is leaking the maximum number of cleartext identifiers and advertising its own misconfiguration. Periodically run this passive profile against your own network as a monitoring control, a rising `JoinRequest` ratio is an early signal of provisioning or coverage failure, not just an attacker's reconnaissance aid. diff --git a/src/content/controls/rfsam-lora-phy-01.md b/src/content/controls/rfsam-lora-phy-01.md index c83f03a..0a53337 100644 --- a/src/content/controls/rfsam-lora-phy-01.md +++ b/src/content/controls/rfsam-lora-phy-01.md @@ -10,13 +10,13 @@ applicability: deferred: false objective: >- Verify that the target's LoRa CSS waveform can be de-chirped and demodulated to - symbols off an SDR — at the spreading factor, bandwidth and SNR seen on the air — + symbols off an SDR, at the spreading factor, bandwidth and SNR seen on the air, so the link-layer LoRaWAN frames it carries can be recovered for the controls above this one. intro: >- LoRa carries no data a higher-layer assessment can read until the chirp is demodulated. This control confirms the PHY de-chirp path works on the target's - SF/BW and recovers symbols reliably at the on-air SNR — soft-decision + SF/BW and recovers symbols reliably at the on-air SNR, soft-decision demodulation extends that reach toward the noise floor, where hard-decision (nearest-bin) decoding silently drops frames. prerequisites: @@ -29,12 +29,12 @@ prerequisites: - 'gr-lora_sdr (GNU Radio CSS receiver), or the Lora-Wideband-Decoder for whole-sub-band intercept' signal: freq: >- - Regional sub-GHz ISM: EU868 (863–870 MHz), US915 (902–928 MHz), AS923, - EU433 (433.05–434.79 MHz), AU915 / CN470 / IN865 / KR920 + Regional sub-GHz ISM: EU868 (863 to 870 MHz), US915 (902 to 928 MHz), AS923, + EU433 (433.05 to 434.79 MHz), AU915 / CN470 / IN865 / KR920 bandwidth: '125 / 250 / 500 kHz (LoRaWAN regional plans)' modulation: >- CSS (Chirp Spread Spectrum); a chirp sweeps the band and the symbol is the - chirp's cyclic start offset. Spreading factor SF7–SF12 trades data rate for + chirp's cyclic start offset. Spreading factor SF7 to SF12 trades data rate for range/sensitivity. skill: intermediate attacks: [] @@ -51,7 +51,7 @@ references: Towards an SDR implementation of LoRa: Reverse-engineering, demodulation strategies and assessment over Rayleigh channel authors: 'A. Marquet, N. Montavont, G. Z. Papadopoulos' - venue: 'Computer Communications, vol. 153, pp. 595–605' + venue: 'Computer Communications, vol. 153, pp. 595 to 605' year: 2020 url: 'https://doi.org/10.1016/j.comcom.2020.02.034' type: paper @@ -63,7 +63,7 @@ references: url: 'https://doi.org/10.1145/3546869' type: paper - key: grlorasdr - title: gr-lora_sdr — GNU Radio SDR implementation of a LoRa transceiver + title: gr-lora_sdr, GNU Radio SDR implementation of a LoRa transceiver authors: J. Tapparel (EPFL TCL) venue: GitHub year: 2026 @@ -97,21 +97,21 @@ lastResearched: 2026-06-14 --- ## Mechanism -LoRa modulates data with Chirp Spread Spectrum (CSS): a sinusoid sweeps linearly across the channel bandwidth, and the *symbol value is the chirp's cyclic start frequency offset* — for spreading factor SF, a symbol carries SF bits, so there are 2^SF distinguishable start offsets [marquet2020] [tapparel2020]. The regional plans use 125/250/500 kHz bandwidths and SF7–SF12, trading data rate for sensitivity (higher SF spreads the same energy over a longer symbol, reaching lower SNR) [rp002]. +LoRa modulates data with Chirp Spread Spectrum (CSS): a sinusoid sweeps linearly across the channel bandwidth, and the *symbol value is the chirp's cyclic start frequency offset*, for spreading factor SF, a symbol carries SF bits, so there are 2^SF distinguishable start offsets [marquet2020] [tapparel2020]. The regional plans use 125/250/500 kHz bandwidths and SF7 to SF12, trading data rate for sensitivity (higher SF spreads the same energy over a longer symbol, reaching lower SNR) [rp002]. -Demodulation is **de-chirping**: the receiver multiplies the incoming chirp by a locally generated reference *down-chirp*, which collapses the swept tone into a single constant-frequency tone, then takes an FFT — the symbol is read off as the index of the FFT bin holding the energy peak [marquet2020] [xu2022]. This is the standard, well-understood LoRa receiver and is what every open-source SDR demodulator implements. +Demodulation is **de-chirping**: the receiver multiplies the incoming chirp by a locally generated reference *down-chirp*, which collapses the swept tone into a single constant-frequency tone, then takes an FFT, the symbol is read off as the index of the FFT bin holding the energy peak [marquet2020] [xu2022]. This is the standard, well-understood LoRa receiver and is what every open-source SDR demodulator implements. -Doing it *reliably on real captures* is the hard part. The energy peak is degraded by sampling time offset (STO) and carrier frequency offset (CFO) between the unsynchronised transmitter and the SDR, and at low SNR the peak can be distorted or buried in noise so the FFT bin is read wrong [xu2022]. A complete receiver therefore needs frame detection (correlating against the up-chirp preamble), then STO and CFO estimation and correction before demodulation; the gr-lora_sdr design implements exactly this chain — preamble sync, CFO/STO compensation, demodulation, Gray-demap, deinterleave, Hamming decode, dewhiten, CRC — and is built to keep decoding at very low SNR [tapparel2020] [grlorasdr] [tapparel2024]. +Doing it *reliably on real captures* is the hard part. The energy peak is degraded by sampling time offset (STO) and carrier frequency offset (CFO) between the unsynchronised transmitter and the SDR, and at low SNR the peak can be distorted or buried in noise so the FFT bin is read wrong [xu2022]. A complete receiver therefore needs frame detection (correlating against the up-chirp preamble), then STO and CFO estimation and correction before demodulation; the gr-lora_sdr design implements exactly this chain, preamble sync, CFO/STO compensation, demodulation, Gray-demap, deinterleave, Hamming decode, dewhiten, CRC, and is built to keep decoding at very low SNR [tapparel2020] [grlorasdr] [tapparel2024]. -Beyond the per-symbol decision, the choice between **hard-decision** (emit the single nearest bin) and **soft-decision** demodulation (carry the per-bin likelihoods forward into the Hamming/FEC stage) changes how many frames survive at the edge of the link budget: soft information lets the decoder recover frames a nearest-bin decoder loses, so hard-decision yields are a lower bound on what is actually on the air [marquet2020] [xu2022]. This is a capture-completeness concern for the auditor, not a vulnerability in the target — hence `info`. +Beyond the per-symbol decision, the choice between **hard-decision** (emit the single nearest bin) and **soft-decision** demodulation (carry the per-bin likelihoods forward into the Hamming/FEC stage) changes how many frames survive at the edge of the link budget: soft information lets the decoder recover frames a nearest-bin decoder loses, so hard-decision yields are a lower bound on what is actually on the air [marquet2020] [xu2022]. This is a capture-completeness concern for the auditor, not a vulnerability in the target, hence `info`. This is a passive PHY check: it recovers symbols and frame bits, but the LoRaWAN application payload stays AES-128 encrypted until the keys are assessed at the crypto layer. There is no off-the-shelf hardware demodulator for LoRa CSS in the standard kit; the de-chirp happens in software on the SDR, which is why capturing and framing live together at the next (link) layer (RFSAM-RES-07). ## Procedure -Work only on signals you are authorised to receive and analyse. Receiving and demodulating LoRa is passive, but capturing third-party traffic may still be regulated in your jurisdiction — have explicit permission for the deployment under test. +Work only on signals you are authorised to receive and analyse. Receiving and demodulating LoRa is passive, but capturing third-party traffic may still be regulated in your jurisdiction, have explicit permission for the deployment under test. -1. **Confirm the band and channel plan** (from RFSAM-LORA-SP / RFSAM-LORA-IG): the regional band sets the centre frequency, and the device profile sets bandwidth and spreading factor. If you only know the band, plan to scan SF7–SF12 [rp002]. +1. **Confirm the band and channel plan** (from RFSAM-LORA-SP / RFSAM-LORA-IG): the regional band sets the centre frequency, and the device profile sets bandwidth and spreading factor. If you only know the band, plan to scan SF7 to SF12 [rp002]. 2. **Capture I/Q over the channel.** Tune the SDR to the channel centre with sample rate ≥ the LoRa bandwidth. Example with an RTL-SDR for EU868 channel 0: ```bash @@ -127,21 +127,21 @@ Work only on signals you are authorised to receive and analyse. Receiving and de ``` Expected output: for each detected frame the receiver prints the demodulated/decoded payload bytes (after Gray-demap, deinterleave, Hamming decode, dewhiten, CRC). A frame that passes CRC is a clean PHY demodulation; CRC failures or "no frame detected" mean the SF/BW guess, sync, or SNR is wrong [grlorasdr] [tapparel2020]. -4. **If you do not yet know SF/BW, or want the whole sub-band at once,** stream wideband I/Q and let the decoder sweep SF7–SF12 across every bandwidth: +4. **If you do not yet know SF/BW, or want the whole sub-band at once,** stream wideband I/Q and let the decoder sweep SF7 to SF12 across every bandwidth: ```bash git clone https://github.com/persistentcache/Lora-Wideband-Decoder # run per its README against a bladeRF/USRP feed; decoded packets, node IDs # and a live waterfall appear in the local Flask web UI ``` - Expected output: decoded LoRa/LoRaWAN/Meshtastic packets surfacing in the web UI as they are demodulated across the band — useful when the exact channel or SF is unknown. + Expected output: decoded LoRa/LoRaWAN/Meshtastic packets surfacing in the web UI as they are demodulated across the band, useful when the exact channel or SF is unknown. 5. **Read the result as a yield.** Note how many frames demodulate cleanly (CRC-OK) versus how many the waterfall shows but the decoder drops. A non-trivial drop rate at the edge of range is the soft-vs-hard-decision gap, and the cue to confirm a soft-decision-capable demodulator before treating the capture as complete [marquet2020] [xu2022]. Export CRC-OK frames as LoRaTap PCAP for the link layer (RFSAM-LORA-LL, RFSAM-RES-07). -6. **Single-board alternative without an SDR de-chirp flow:** the CatSniffer's SX1262 can capture and decode LoRa into Wireshark via `catnip` once region/SF/BW are set — a hardware-radio capture path to cross-check the SDR demodulation against. +6. **Single-board alternative without an SDR de-chirp flow:** the CatSniffer's SX1262 can capture and decode LoRa into Wireshark via `catnip` once region/SF/BW are set, a hardware-radio capture path to cross-check the SDR demodulation against. ## Field case -A representative, reproducible setup (the values below marked `[FILL]` are *not* measured RFSAM results — substitute your own bench numbers): +A representative, reproducible setup (the values below marked `[FILL]` are *not* measured RFSAM results, substitute your own bench numbers): Target: an EU868 LoRaWAN sensor, channel 0 (868.1 MHz), SF7, BW 125 kHz. Capture with `rtl_sdr -f 868100000 -s 1000000 -g 40 -n 6000000 lora_eu868_ch0.iq`, then demodulate with gr-lora_sdr (sf=7, bw=125000) and observe the per-frame decode output. Repeat the same capture with the demodulator in hard-decision mode and compare CRC-OK frame yield. @@ -149,14 +149,14 @@ On a clean, close-range capture both modes recover essentially every frame, and > [!NOTE] [FILL: measured CRC-OK frame yield, hard vs soft-decision, at a recorded SNR for one capture]. Earlier stub copy asserted "~25% more bits recovered"; that specific figure is not an RFSAM measurement and is SF/BW/SNR/decoder-dependent, so it is withheld rather than fabricated. The *direction* (soft ≥ hard at low SNR) is supported by [marquet2020] and [xu2022]; the magnitude must be measured on the actual target capture. -For a passive survey aiming to enumerate a network, every frame the demodulator drops is potentially a device or a join you never see — which is why this PHY-completeness check precedes the link-layer enumeration rather than being assumed. +For a passive survey aiming to enumerate a network, every frame the demodulator drops is potentially a device or a join you never see, which is why this PHY-completeness check precedes the link-layer enumeration rather than being assumed. ## Remediation This control verifies an auditor capability, so most of the action is auditor-side; the developer/integrator/operator guidance is about *what the demodulability of the PHY implies for the deployment*. -- **Auditor.** Use a soft-decision-capable LoRa demodulator (gr-lora_sdr class) for assessment, and treat hard-decision-only yields as a lower bound on what is on the air, not a complete enumeration [marquet2020] [xu2022]. Confirm the SF/BW set actually in use (devices may use multiple data rates) before declaring a capture complete; sweep SF7–SF12 if the profile is unknown. +- **Auditor.** Use a soft-decision-capable LoRa demodulator (gr-lora_sdr class) for assessment, and treat hard-decision-only yields as a lower bound on what is on the air, not a complete enumeration [marquet2020] [xu2022]. Confirm the SF/BW set actually in use (devices may use multiple data rates) before declaring a capture complete; sweep SF7 to SF12 if the profile is unknown. -- **Developer / integrator.** The CSS PHY is, by design, open and demodulable — its protection is not obscurity but the AES-128 crypto layer (FRMPayload confidentiality, MIC integrity). Do not treat "LoRa is hard to demodulate" as a security property: an SDR plus open-source software recovers the frames. Ensure all sensitive data and commands rely on the LoRaWAN crypto, not on the difficulty of demodulation, and assess that crypto under the CR-layer controls. +- **Developer / integrator.** The CSS PHY is, by design, open and demodulable, its protection is not obscurity but the AES-128 crypto layer (FRMPayload confidentiality, MIC integrity). Do not treat "LoRa is hard to demodulate" as a security property: an SDR plus open-source software recovers the frames. Ensure all sensitive data and commands rely on the LoRaWAN crypto, not on the difficulty of demodulation, and assess that crypto under the CR-layer controls. - **Operator.** Assume any LoRa transmission in range is demodulable to frames by a passive listener; plan the threat model around the link-layer metadata that travels in clear (DevAddr, and the join-request DevEUI/JoinEUI/DevNonce) being observable, and around the encrypted payload's confidentiality resting entirely on key management. PHY demodulation itself exposes no payload, but it is the prerequisite for every analysis above it. diff --git a/src/content/controls/rfsam-lora-sp-01.md b/src/content/controls/rfsam-lora-sp-01.md index 149ec79..5be9421 100644 --- a/src/content/controls/rfsam-lora-sp-01.md +++ b/src/content/controls/rfsam-lora-sp-01.md @@ -12,7 +12,7 @@ objective: >- Confirm the toolchain can recover LoRa CSS transmissions at strongly negative SNR (below the thermal noise floor) and use that capability to survey the regional ISM sub-band for the channels, bandwidths and spreading factors a - target network actually uses — before concluding a band is quiet. + target network actually uses, before concluding a band is quiet. intro: >- LoRa's chirp spread spectrum is engineered to be received well below the thermal noise floor, so an energy-only spectrum survey will declare a busy @@ -21,7 +21,7 @@ intro: >- prerequisites: hardware: - >- - An RX SDR covering the sub-GHz ISM band: RTL-SDR Blog V4 (cheap, narrow — + An RX SDR covering the sub-GHz ISM band: RTL-SDR Blog V4 (cheap, narrow, enough to watch one channel of a sub-GHz band) or a HackRF One (~20 MHz instantaneous bandwidth, to watch a whole sub-band at once). - >- @@ -35,10 +35,10 @@ prerequisites: / ChirpCat for the CatSniffer / gateway paths. signal: freq: >- - Regional sub-GHz ISM: EU868 (863–870 MHz) · US915 (902–928 MHz) · AS923 · - EU433 (433.05–434.79 MHz) — the region sets the channel plan you survey. - bandwidth: '125 / 250 / 500 kHz LoRaWAN channels (SX127x/SX126x also do 7.8–62.5 kHz, unused by LoRaWAN)' - modulation: 'CSS (Chirp Spread Spectrum); data in the chirp cyclic start offset, SF7–SF12' + Regional sub-GHz ISM: EU868 (863 to 870 MHz) · US915 (902 to 928 MHz) · AS923 · + EU433 (433.05 to 434.79 MHz), the region sets the channel plan you survey. + bandwidth: '125 / 250 / 500 kHz LoRaWAN channels (SX127x/SX126x also do 7.8 to 62.5 kHz, unused by LoRaWAN)' + modulation: 'CSS (Chirp Spread Spectrum); data in the chirp cyclic start offset, SF7 to SF12' skill: intermediate attacks: [] references: @@ -57,7 +57,7 @@ references: url: 'https://arxiv.org/abs/2002.08208' type: paper - key: grlora_sdr - title: 'gr-lora_sdr — GNU Radio SDR implementation of a LoRa transceiver (operates at very low SNR)' + title: 'gr-lora_sdr, GNU Radio SDR implementation of a LoRa transceiver (operates at very low SNR)' authors: J. Tapparel (TCL, EPFL) venue: GitHub year: 2024 @@ -95,17 +95,17 @@ lastResearched: 2026-06-14 --- ## Mechanism -LoRa is a chirp spread spectrum (CSS) modulation derived from work later acquired by Semtech: a linear frequency chirp sweeps the channel bandwidth, and data is encoded in the chirp's cyclic start offset. The spreading factor (SF7–SF12) trades data rate for range and sensitivity, higher SF meaning a longer, slower symbol [semtech2019longrange]. The receiver de-chirps by multiplying the incoming chirp by a reference down-chirp and taking an FFT, which collapses each symbol into a single frequency bin. Spreading the symbol energy over a long chirp and integrating it back at the receiver yields processing gain — the reason a LoRa link can close on signals buried in noise. +LoRa is a chirp spread spectrum (CSS) modulation derived from work later acquired by Semtech: a linear frequency chirp sweeps the channel bandwidth, and data is encoded in the chirp's cyclic start offset. The spreading factor (SF7 to SF12) trades data rate for range and sensitivity, higher SF meaning a longer, slower symbol [semtech2019longrange]. The receiver de-chirps by multiplying the incoming chirp by a reference down-chirp and taking an FFT, which collapses each symbol into a single frequency bin. Spreading the symbol energy over a long chirp and integrating it back at the receiver yields processing gain, the reason a LoRa link can close on signals buried in noise. -The operationally important consequence for a spectrum survey: Semtech states the benefit of LoRa spread spectrum is "the ability to receive up to 20 dB below the thermal noise floor" [semtech2019longrange]. A plain FFT / energy-detector waterfall only shows energy above the noise floor, so a busy LoRaWAN deployment can be completely invisible to a naive survey — the transmissions are real, just sub-noise. Recovering them requires de-chirping, not just looking. The reference open-source implementation that does this is gr-lora_sdr, a full GNU Radio LoRa transceiver "with all the necessary receiver components to operate correctly even at very low SNRs", built at EPFL's Telecommunication Circuits Laboratory [grlora_sdr][tapparel2020grlora]. Research on neural-enhanced demodulation (NELoRa) further confirms that the interesting LoRa demodulation regime is at very low / negative SNR, and works to push the threshold even lower [li2021nelora]. +The operationally important consequence for a spectrum survey: Semtech states the benefit of LoRa spread spectrum is "the ability to receive up to 20 dB below the thermal noise floor" [semtech2019longrange]. A plain FFT / energy-detector waterfall only shows energy above the noise floor, so a busy LoRaWAN deployment can be completely invisible to a naive survey, the transmissions are real, just sub-noise. Recovering them requires de-chirping, not just looking. The reference open-source implementation that does this is gr-lora_sdr, a full GNU Radio LoRa transceiver "with all the necessary receiver components to operate correctly even at very low SNRs", built at EPFL's Telecommunication Circuits Laboratory [grlora_sdr][tapparel2020grlora]. Research on neural-enhanced demodulation (NELoRa) further confirms that the interesting LoRa demodulation regime is at very low / negative SNR, and works to push the threshold even lower [li2021nelora]. -The frequencies to survey are fixed by region, not chosen by the auditor: the LoRaWAN Regional Parameters specification defines the channel plans — EU868 (863–870 MHz), US915 (902–928 MHz), AS923, EU433 and others — including the 125/250/500 kHz channel bandwidths in play [loraalliance_rp002]. LoRa devices are duty-cycle limited and often transmit infrequently, so "I saw nothing" after a short look is not evidence of an empty band. This control is observational only — it establishes capture feasibility and maps the channel plan; it does not decode payloads or attack the network (those are the LL/CR/AT controls). There is no device-side vulnerability here, hence `info` criticality: the risk being managed is a false negative in the assessment itself. +The frequencies to survey are fixed by region, not chosen by the auditor: the LoRaWAN Regional Parameters specification defines the channel plans, EU868 (863 to 870 MHz), US915 (902 to 928 MHz), AS923, EU433 and others, including the 125/250/500 kHz channel bandwidths in play [loraalliance_rp002]. LoRa devices are duty-cycle limited and often transmit infrequently, so "I saw nothing" after a short look is not evidence of an empty band. This control is observational only, it establishes capture feasibility and maps the channel plan; it does not decode payloads or attack the network (those are the LL/CR/AT controls). There is no device-side vulnerability here, hence `info` criticality: the risk being managed is a false negative in the assessment itself. ## Procedure All steps below are passive receive-only. No transmission is involved; even so, run any survey only within a band you are authorised to monitor and in line with local spectrum regulations. -1. Establish the region and channel plan from the LoRaWAN Regional Parameters spec [loraalliance_rp002] (typically already recorded by the LoRa IG control). Example: EU868 default channels cluster around 868.1 / 868.3 / 868.5 MHz at 125 kHz; US915 uplinks span 902.3–914.9 MHz at 125 kHz (plus 500 kHz channels). +1. Establish the region and channel plan from the LoRaWAN Regional Parameters spec [loraalliance_rp002] (typically already recorded by the LoRa IG control). Example: EU868 default channels cluster around 868.1 / 868.3 / 868.5 MHz at 125 kHz; US915 uplinks span 902.3 to 914.9 MHz at 125 kHz (plus 500 kHz channels). 2. Watch the sub-band live on a waterfall to spot the unmistakable diagonal CSS chirp sweeps. With an RTL-SDR or HackRF in gqrx: ```bash @@ -119,7 +119,7 @@ All steps below are passive receive-only. No transmission is involved; even so, ```bash hackrf_transfer -r lora_868_3.iq -f 868300000 -s 2000000 -a 1 -l 32 -g 40 ``` - Expected: a growing `.iq` file and `0` reported dropped/overflow samples. A capture with overflows is silently incomplete — re-run at a lower sample rate or with a faster disk if you see them. + Expected: a growing `.iq` file and `0` reported dropped/overflow samples. A capture with overflows is silently incomplete, re-run at a lower sample rate or with a faster disk if you see them. 4. Prove sub-noise reception: de-chirp the capture and confirm symbols resolve that were invisible on the plain waterfall. Run the gr-lora_sdr receiver flowgraph/example against a known transmitter at known SF/BW first (RFSAM-RES-07) [grlora_sdr]: ```bash @@ -127,35 +127,35 @@ All steps below are passive receive-only. No transmission is involved; even so, # capture's centre freq, bandwidth (125000) and the candidate SF. gnuradio-companion gr-lora_sdr/examples/lora_RX.grc ``` - Expected: decoded LoRa frames (a recovered PHYPayload, even if the application bytes stay AES-128 encrypted) printed by the flowgraph. Recovering frames whose energy never rose above the FFT noise floor is the positive result this control is after. Sweep SF7–SF12 if the SF is unknown — the de-chirp only locks when the reference down-chirp matches the transmitter's SF/BW. + Expected: decoded LoRa frames (a recovered PHYPayload, even if the application bytes stay AES-128 encrypted) printed by the flowgraph. Recovering frames whose energy never rose above the FFT noise floor is the positive result this control is after. Sweep SF7 to SF12 if the SF is unknown, the de-chirp only locks when the reference down-chirp matches the transmitter's SF/BW. 5. No-SDR / multi-channel alternatives, depending on kit: ```bash # CatSniffer SX1262 as a real-time sub-GHz/LoRa spectrum view: catnip lora spectrum # live SX1262 spectrum scanner ``` - A multi-channel LoRaWAN gateway (RAK WisGate Connect) feeding ChirpCat logs every channel at once and clusters packets by RF characteristics — the fastest way to map a whole channel plan if you have the gateway. + A multi-channel LoRaWAN gateway (RAK WisGate Connect) feeding ChirpCat logs every channel at once and clusters packets by RF characteristics, the fastest way to map a whole channel plan if you have the gateway. 6. Record the survey result: which regional band, which centre frequencies/channels carry traffic, the bandwidths, and (where de-chirp locked) the spreading factors observed. This map scopes the capture target for the LoRa LL/CR controls. ## Field case -Illustrative walkthrough — substitute the values you capture: run an EU868 survey with an RTL-SDR Blog V4 on 868.3 MHz in gqrx. The waterfall typically looks almost flat — a handful of faint diagonal streaks during the watch window, easy to dismiss as "a couple of devices, mostly quiet". Capturing the channel to I/Q and de-chirping it with gr-lora_sdr swept across SF7–SF12 is where the gap shows: frames can resolve at several spreading factors, including transmissions that left no visible mark on the plain FFT at all. The point this control makes is exactly that contrast — an energy-detector read ("band mostly empty") and a de-chirped read of the same capture can disagree completely, and only the de-chirped read reflects the real occupancy. +Illustrative walkthrough, substitute the values you capture: run an EU868 survey with an RTL-SDR Blog V4 on 868.3 MHz in gqrx. The waterfall typically looks almost flat, a handful of faint diagonal streaks during the watch window, easy to dismiss as "a couple of devices, mostly quiet". Capturing the channel to I/Q and de-chirping it with gr-lora_sdr swept across SF7 to SF12 is where the gap shows: frames can resolve at several spreading factors, including transmissions that left no visible mark on the plain FFT at all. The point this control makes is exactly that contrast, an energy-detector read ("band mostly empty") and a de-chirped read of the same capture can disagree completely, and only the de-chirped read reflects the real occupancy. Concrete numbers to record in a worked write-up (mark unmeasured values rather than inventing them): - Region / sub-band surveyed: EU868, centre 868.3 MHz, 125 kHz channel. - Watch window before declaring "quiet": [FILL: minutes/hours observed]. - Frames the plain FFT showed vs frames gr-lora_sdr recovered after de-chirp: [FILL: counts]. -- Lowest SNR at which a frame still decoded: [FILL: measured dB] — Semtech's stated envelope is up to 20 dB below the thermal noise floor [semtech2019longrange]. +- Lowest SNR at which a frame still decoded: [FILL: measured dB], Semtech's stated envelope is up to 20 dB below the thermal noise floor [semtech2019longrange]. - Spreading factors observed once de-chirp locked: [FILL: e.g. SF7, SF9, SF12]. -The reproducible lesson is the gap itself: establishing the de-chirp / processing-gain baseline is what lets a passive observer see an entire LoRaWAN deployment that an energy-only survey misses. The bracketed `[FILL: …]` values above are placeholders — fill them from a real survey before citing this section as a measured finding; do not present the placeholders as measured results. +The reproducible lesson is the gap itself: establishing the de-chirp / processing-gain baseline is what lets a passive observer see an entire LoRaWAN deployment that an energy-only survey misses. The bracketed `[FILL: …]` values above are placeholders, fill them from a real survey before citing this section as a measured finding; do not present the placeholders as measured results. ## Remediation -This control verifies an auditor capability and guards against a false-negative survey — sub-noise reception is an inherent property of CSS, so there is no patch that "fixes" it. Guidance is therefore about not being misled and about the limited operator hardening that exists at this layer. +This control verifies an auditor capability and guards against a false-negative survey, sub-noise reception is an inherent property of CSS, so there is no patch that "fixes" it. Guidance is therefore about not being misled and about the limited operator hardening that exists at this layer. - **Auditor / assessor:** never conclude a regional sub-band is unused from an energy-only waterfall. Always confirm with a de-chirping capture (gr-lora_sdr or a gateway feed) and account for duty-cycle-limited, infrequent transmitters by extending the watch window. Treat band occupancy as established only after de-chirp recovers (or fails to recover) frames. -- **Developer / integrator:** recognise that transmissions are observable to any passive receiver even when they sit below the noise floor — physical-layer "stealth" is not a security property. Confidentiality must come from the LoRaWAN crypto layer (AES-128 AppSKey on FRMPayload), not from signals being hard to see. Identifiers carried in clear (DevAddr in data frames; DevEUI/JoinEUI/DevNonce in joins) are exposed to anyone who can de-chirp, which is the premise the LoRa LL/CR controls build on. -- **Operator:** assume a motivated observer can map your channel plan and device activity passively. Where this matters (e.g. activity-pattern leakage), favour channel/SF diversity and frame-counter hygiene, and rely on the upper-layer controls for confidentiality and replay protection rather than on transmission obscurity. Tool and capability corpora here are representative — verify current SDR/demodulator maturity for your region and spreading factors before relying on a survey result. +- **Developer / integrator:** recognise that transmissions are observable to any passive receiver even when they sit below the noise floor, physical-layer "stealth" is not a security property. Confidentiality must come from the LoRaWAN crypto layer (AES-128 AppSKey on FRMPayload), not from signals being hard to see. Identifiers carried in clear (DevAddr in data frames; DevEUI/JoinEUI/DevNonce in joins) are exposed to anyone who can de-chirp, which is the premise the LoRa LL/CR controls build on. +- **Operator:** assume a motivated observer can map your channel plan and device activity passively. Where this matters (e.g. activity-pattern leakage), favour channel/SF diversity and frame-counter hygiene, and rely on the upper-layer controls for confidentiality and replay protection rather than on transmission obscurity. Tool and capability corpora here are representative, verify current SDR/demodulator maturity for your region and spreading factors before relying on a survey result. diff --git a/src/content/controls/rfsam-lte-ig-01.md b/src/content/controls/rfsam-lte-ig-01.md index 493cfa1..b915b77 100644 --- a/src/content/controls/rfsam-lte-ig-01.md +++ b/src/content/controls/rfsam-lte-ig-01.md @@ -12,14 +12,14 @@ objective: >- Establish which baseband (modem SoC + firmware) the target device runs and, where the network is in scope, which RAN/core implementation and version the eNodeB/EPC runs, then determine whether either carries a known, named, - CVE-tracked vulnerability — before any behavioural or over-the-air testing. + CVE-tracked vulnerability, before any behavioural or over-the-air testing. intro: >- LTE has two distinct software surfaces worth inventorying before any RF work: the device-side baseband (the modem SoC running its own RTOS, reachable over the air) and, where the network is in scope, the RAN/core stack (eNodeB + EPC, increasingly open-source). Identify both and cross-reference the published corpora. Unlike BLE, the BSAM registry covers only Bluetooth, so there is no - BSAM information-gathering control to defer to — RFSAM owns this control end to + BSAM information-gathering control to defer to, RFSAM owns this control end to end. prerequisites: hardware: @@ -29,7 +29,7 @@ prerequisites: - 'An AT terminal for reading modem identity (AT+CGMI / AT+CGMM / AT+CGMR); QCSuper or MobileInsight to confirm the Qualcomm baseband and read its firmware from the DIAG feed' - 'For network-side scope: the source tree / package metadata of the RAN-core stack under test (srsRAN, Open5GS, OpenAirInterface, Magma, NextEPC) to read its version' signal: - freq: 'Licensed cellular — common bands ~700 MHz to 2.6 GHz (full E-UTRA ~450 MHz–3.8 GHz); FDD and TDD' + freq: 'Licensed cellular, common bands ~700 MHz to 2.6 GHz (full E-UTRA ~450 MHz to 3.8 GHz); FDD and TDD' bandwidth: '1.4 / 3 / 5 / 10 / 15 / 20 MHz channels; carrier identified by EARFCN' modulation: 'Downlink OFDMA, uplink SC-FDMA; QPSK/16/64/256-QAM' skill: intermediate @@ -49,7 +49,7 @@ attacks: Domain-informed (ASN.1-structure-aware) fuzzing of LTE/5G RAN-core interfaces that reported 119 vulnerabilities (the paper states 93 assigned CVEs in its abstract and 96 in its introduction) across seven cellular core - implementations, three of which are also 5G. Representative — check the + implementations, three of which are also 5G. Representative, check the per-stack advisories for the build in scope. - name: UNISOC NAS-parsing buffer overflow cve: @@ -65,7 +65,7 @@ attacks: potential for code execution. preconditions: >- Target device uses an affected, unpatched UNISOC baseband; attacker can - deliver the malformed NAS message — in practice from a rogue cell the device + deliver the malformed NAS message, in practice from a rogue cell the device camps on. summary: >- Missing bounds checks in UNISOC NAS message parsing, found by Check Point @@ -88,7 +88,7 @@ attacks: summary: >- Use-after-free in the Qualcomm DSP/FASTRPC path, credited to Google Project Zero and Amnesty Security Lab and flagged by Google TAG as possibly - exploited — a baseband-adjacent SoC bug the inventory should surface. + exploited, a baseband-adjacent SoC bug the inventory should surface. - name: LLFuzz baseband lower-layer (L2) memory corruption refs: - hoang2025llfuzz @@ -108,8 +108,8 @@ attacks: refs: - weinmann2012baseband impact: >- - Arbitrary code execution on the baseband processor — below the application - processor and its hardening — from over-the-air message handling. + Arbitrary code execution on the baseband processor, below the application + processor and its hardening, from over-the-air message handling. preconditions: >- A memory-corruption bug in the baseband's over-the-air protocol stack and an attacker able to deliver the triggering messages (e.g. a rogue cell). @@ -181,9 +181,9 @@ lastResearched: 2026-06-14 The baseband is a second computer inside every cellular device: a modem SoC running its own real-time OS on a dedicated core, with firmware that parses attacker-influenceable radio messages over the air. Memory-corruption bugs there yield code execution *below* the application processor and its hardening (ASLR/DEP/code-signing), which is exactly the gap Weinmann's foundational WOOT 2012 work demonstrated by exploiting memory corruptions in deployed cellular protocol stacks [weinmann2012baseband]. That surface has stayed live and moved down the stack: the UNISOC NAS-parser overflow is a CVE-tracked remote DoS/RCE in the modem's Non-Access-Stratum message parsing [cpr2022unisoc] [cve-2022-20210], and LLFuzz's over-the-air fuzzing of the *lower* layers (PDCP/RLC/MAC) found eleven previously-unknown memory corruptions across fifteen commercial basebands from five vendors, seven of them assigned CVEs [hoang2025llfuzz]. Baseband-adjacent SoC bugs reach real targeted-surveillance use, too: CVE-2024-43047, a use-after-free in the Qualcomm DSP/FASTRPC path, was credited to Google Project Zero and Amnesty Security Lab and flagged by Google TAG as possibly under limited, targeted exploitation [cve-2024-43047] [securityweek2024qualcomm]. -Symmetrically, where the network side is in scope, the eNodeB/EPC parses attacker-influenced RRC/NAS messages and is increasingly open-source. The RANsacked study applied ASN.1-structure-aware fuzzing to the RAN-core interface and reported 119 vulnerabilities (the paper gives the assigned-CVE total as 93 in its abstract and 96 in its introduction) across seven cellular core implementations — srsRAN/srsEPC, Open5GS, Magma, OpenAirInterface, NextEPC, SD-Core and HPE Athonet, three of which (Magma, Open5GS, OAI) are also exercised as 5G cores — several of which let a single unauthenticated, pre-authentication packet persistently crash the MME/AMF, with the NAS-reachable findings triggerable before the UE is verified (i.e. without a valid SIM) [bennett2024ransacked]. That makes the implementation-and-version of an in-scope core a finding in its own right: an unpatched build can be matched to a known single-packet crash on inventory alone. +Symmetrically, where the network side is in scope, the eNodeB/EPC parses attacker-influenced RRC/NAS messages and is increasingly open-source. The RANsacked study applied ASN.1-structure-aware fuzzing to the RAN-core interface and reported 119 vulnerabilities (the paper gives the assigned-CVE total as 93 in its abstract and 96 in its introduction) across seven cellular core implementations, srsRAN/srsEPC, Open5GS, Magma, OpenAirInterface, NextEPC, SD-Core and HPE Athonet, three of which (Magma, Open5GS, OAI) are also exercised as 5G cores, several of which let a single unauthenticated, pre-authentication packet persistently crash the MME/AMF, with the NAS-reachable findings triggerable before the UE is verified (i.e. without a valid SIM) [bennett2024ransacked]. That makes the implementation-and-version of an in-scope core a finding in its own right: an unpatched build can be matched to a known single-packet crash on inventory alone. -This control therefore inventories two things — (1) the device baseband vendor and firmware version, and (2), where the eNodeB/EPC is in scope, the RAN/core implementation and version — and cross-references both against the corpora above. It is the LTE analogue of RFSAM-BLE-IG-01; the difference is that BLE defers the corpus check to BSAM, whereas the BSAM registry has no cellular control, so RFSAM owns the cross-reference here. The corpora below are representative; CVE inventories date fast, so confirm against current vendor security bulletins for the exact chipset/build in scope rather than treating any list as exhaustive [bennett2024ransacked]. No single RANsacked CVE ID is asserted here: the paper's per-stack, per-version CVE mapping lives in its appendix (Table 6), so pull the specific CVE IDs for the exact build in scope from the paper or NVD before relying on any one of them. +This control therefore inventories two things, (1) the device baseband vendor and firmware version, and (2), where the eNodeB/EPC is in scope, the RAN/core implementation and version, and cross-references both against the corpora above. It is the LTE analogue of RFSAM-BLE-IG-01; the difference is that BLE defers the corpus check to BSAM, whereas the BSAM registry has no cellular control, so RFSAM owns the cross-reference here. The corpora below are representative; CVE inventories date fast, so confirm against current vendor security bulletins for the exact chipset/build in scope rather than treating any list as exhaustive [bennett2024ransacked]. No single RANsacked CVE ID is asserted here: the paper's per-stack, per-version CVE mapping lives in its appendix (Table 6), so pull the specific CVE IDs for the exact build in scope from the paper or NVD before relying on any one of them. ## Procedure @@ -200,7 +200,7 @@ All steps below are passive inventory on equipment you own or are authorised to AT+CGMM AT+CGMR ``` - Expected: `AT+CGMI` returns the manufacturer (e.g. `SIMCOM INCORPORATED` / `QUALCOMM`), `AT+CGMM` the model, and `AT+CGMR` the firmware/revision string (e.g. `LE11B...`). Record the vendor and exact revision — this is the key you will look up. `AT+CPSI?` additionally returns the serving system mode, operator (MCC-MNC), band, EARFCN and Cell ID if you also want the cell identity. + Expected: `AT+CGMI` returns the manufacturer (e.g. `SIMCOM INCORPORATED` / `QUALCOMM`), `AT+CGMM` the model, and `AT+CGMR` the firmware/revision string (e.g. `LE11B...`). Record the vendor and exact revision, this is the key you will look up. `AT+CPSI?` additionally returns the serving system mode, operator (MCC-MNC), band, EARFCN and Cell ID if you also want the cell identity. 2. **Confirm the baseband family from the DIAG feed.** Qualcomm-based modems (the SIM7600 included) expose a `/dev/diag` port; QCSuper reads the chipset and signalling from it: ```bash @@ -221,11 +221,11 @@ All steps below are passive inventory on equipment you own or are authorised to 5. **Cross-reference the RAN/core stack** version against RANsacked [bennett2024ransacked] and the upstream issue trackers / release notes for that build. Flag any version at or below a build named in a single-packet-MME-crash finding. -6. **Record patch status and risk.** Flag end-of-life basebands with no OEM patch path, and unpatched open-source cores reachable by attacker-influenced packets, as high-risk on inventory alone — before any custom fuzzing or over-the-air testing. +6. **Record patch status and risk.** Flag end-of-life basebands with no OEM patch path, and unpatched open-source cores reachable by attacker-influenced packets, as high-risk on inventory alone, before any custom fuzzing or over-the-air testing. ## Field case -Illustrative walkthrough — substitute the values you capture. Working a fixed-LTE CPE (a UNISOC-based router) in an authorised lab, the inventory step runs before any RF capture. `AT+CGMI` / `AT+CGMM` / `AT+CGMR` over the device's AT port return the UNISOC modem family and a firmware revision string; if the device's reported security-patch level predates the UNISOC NAS fix, then on inventory alone that places the device within the published exposure window of the UNISOC NAS-parsing overflow [cve-2022-20210] [cpr2022unisoc] — a CVE-tracked remote modem-crash reachable from a NAS message — so the engagement is reframed around that known finding rather than starting from blind fuzzing. The exact firmware revision and patch date are device-specific and are recorded per engagement: +Illustrative walkthrough, substitute the values you capture. Working a fixed-LTE CPE (a UNISOC-based router) in an authorised lab, the inventory step runs before any RF capture. `AT+CGMI` / `AT+CGMM` / `AT+CGMR` over the device's AT port return the UNISOC modem family and a firmware revision string; if the device's reported security-patch level predates the UNISOC NAS fix, then on inventory alone that places the device within the published exposure window of the UNISOC NAS-parsing overflow [cve-2022-20210] [cpr2022unisoc], a CVE-tracked remote modem-crash reachable from a NAS message, so the engagement is reframed around that known finding rather than starting from blind fuzzing. The exact firmware revision and patch date are device-specific and are recorded per engagement: - Baseband vendor/family: UNISOC (confirmed via `AT+CGMI`/`AT+CGMM`) - Firmware revision read: [FILL: AT+CGMR revision string for the unit under test] @@ -238,8 +238,8 @@ The symmetric network-side version applies unchanged: if the in-scope eNodeB/EPC ## Remediation -**Developer (baseband / stack vendors).** Apply memory-safety discipline to NAS and lower-layer (PDCP/RLC/MAC/RRC) parsers — bounds-check every length-prefixed field — since these are the surfaces the UNISOC overflow [cve-2022-20210] and the LLFuzz L2 corpus [hoang2025llfuzz] hit; harden the baseband core toward parity with the application processor, the gap Weinmann identified [weinmann2012baseband]. For RAN/core implementations, treat RAN-facing inputs as untrusted and fuzz the ASN.1 decode paths the way RANsacked did [bennett2024ransacked]. +**Developer (baseband / stack vendors).** Apply memory-safety discipline to NAS and lower-layer (PDCP/RLC/MAC/RRC) parsers, bounds-check every length-prefixed field, since these are the surfaces the UNISOC overflow [cve-2022-20210] and the LLFuzz L2 corpus [hoang2025llfuzz] hit; harden the baseband core toward parity with the application processor, the gap Weinmann identified [weinmann2012baseband]. For RAN/core implementations, treat RAN-facing inputs as untrusted and fuzz the ASN.1 decode paths the way RANsacked did [bennett2024ransacked]. **Integrator (device OEMs / network operators).** Maintain a current baseband-firmware update path and surface the modem patch level, not just the application-processor patch date; track each shipped chipset against its vendor's security bulletins. For deployed cores, pin the RAN/core build to a patched release and subscribe to the upstream advisories for that stack. -**Operator (defenders / assessors).** Inventory first: record baseband vendor + firmware revision and (where in scope) the RAN/core implementation + version, and match both against current advisories and the corpora here — flag end-of-life basebands and unpatched cores as high-risk. Never expose an unauthenticated MME/AMF to attacker-reachable packets [bennett2024ransacked]. Any step that goes beyond inventory into transmitting (standing up a test cell to deliver the triggering message) is authorised-testing-only: your own equipment and test SIMs, inside RF shielding, under explicit permission. There is no BSAM cellular control to defer to — this cross-reference is RFSAM's domain. +**Operator (defenders / assessors).** Inventory first: record baseband vendor + firmware revision and (where in scope) the RAN/core implementation + version, and match both against current advisories and the corpora here, flag end-of-life basebands and unpatched cores as high-risk. Never expose an unauthenticated MME/AMF to attacker-reachable packets [bennett2024ransacked]. Any step that goes beyond inventory into transmitting (standing up a test cell to deliver the triggering message) is authorised-testing-only: your own equipment and test SIMs, inside RF shielding, under explicit permission. There is no BSAM cellular control to defer to, this cross-reference is RFSAM's domain. diff --git a/src/content/controls/rfsam-lte-ll-01.md b/src/content/controls/rfsam-lte-ll-01.md index 7235e78..fb6c006 100644 --- a/src/content/controls/rfsam-lte-ll-01.md +++ b/src/content/controls/rfsam-lte-ll-01.md @@ -9,26 +9,26 @@ applicability: deferred: false objective: >- Determine, from a purely passive capture, which LTE control-channel and - broadcast information a receiver can recover without transmitting — active + broadcast information a receiver can recover without transmitting, active RNTIs and per-cell scheduling from the PDCCH, cell configuration from the SIBs, and subscriber identifiers (S-TMSI, and where mis-configured, IMSI) - from the paging channel — and document the identity- and tracking-exposure + from the paging channel, and document the identity- and tracking-exposure that follows. intro: >- LTE shouts its control and broadcast information in the clear. A passive receiver that has recovered the resource grid can blind-decode the PDCCH to enumerate active RNTIs and scheduling, read the SIBs for cell identity, and watch the paging channel for the temporary (and sometimes permanent) - subscriber identifiers — all without ever keying up. This control inventories + subscriber identifiers, all without ever keying up. This control inventories exactly what is recoverable passively and the privacy exposure it creates. prerequisites: hardware: - 'A coherent, ideally GPSDO-disciplined SDR for clean OFDM grid recovery: USRP B210 (preferred), bladeRF 2.0 micro, or SignalSDR Pro; a free-running HackRF One can do cell search and MIB/SIB but is twitchier on the PDCCH' - - 'For low LTE bands only, an RTL-SDR V4 reaches up to ~1.766 GHz (700/800 MHz carriers) but not the 1.8–2.6 GHz carriers' + - 'For low LTE bands only, an RTL-SDR V4 reaches up to ~1.766 GHz (700/800 MHz carriers) but not the 1.8 to 2.6 GHz carriers' software: - 'LTESniffer (downlink/uplink PDCCH+PDSCH/PUSCH eavesdropper) or FALCON (real-time whole-PDCCH blind decode); srsRAN 4G (srsUE cell search + MIB/SIB receiver, MAC-LTE/RRC PCAP); Wireshark for GSMTAP / MAC-LTE dissection' signal: - freq: 'Licensed cellular, ~700 MHz–2.6 GHz (full E-UTRA ~450 MHz–3.8 GHz); the carrier EARFCN/band must be known first (see RFSAM-RES-08)' + freq: 'Licensed cellular, ~700 MHz to 2.6 GHz (full E-UTRA ~450 MHz to 3.8 GHz); the carrier EARFCN/band must be known first (see RFSAM-RES-08)' bandwidth: '1.4 / 3 / 5 / 10 / 15 / 20 MHz channel widths; a 20 MHz carrier fits one HackRF/B210 view' modulation: 'Downlink OFDMA (PDCCH/PDSCH), uplink SC-FDMA; QPSK/16/64/256-QAM; 10 ms frame → 10×1 ms subframes → 2×0.5 ms slots' skill: advanced @@ -40,7 +40,7 @@ attacks: An attacker within radio range correlates paging (S-TMSI) and the in-the-clear broadcast/SIB configuration to confirm a target's presence in a tracking area and, with the documented smart-paging trigger, - narrow it toward a single cell — a location/privacy leak with no + narrow it toward a single cell, a location/privacy leak with no transmission required for the core observation. preconditions: >- Radio proximity to the serving cell and a receiver that recovers the grid @@ -71,7 +71,7 @@ attacks: impact: >- The clear-text attach / paging / detach procedures this control reads passively are the same procedures that model checking shows to be - vulnerable to authentication relay, paging-channel hijack and DoS — the + vulnerable to authentication relay, paging-channel hijack and DoS, the active attacks the passive picture scopes and informs. preconditions: >- Carrying these out is active and out of scope for this passive control; @@ -110,7 +110,7 @@ references: url: 'https://pure.kaist.ac.kr/en/publications/ltesniffer-an-open-source-lte-downlinkuplink-eavesdropper/' type: paper - key: ltesniffer-repo - title: 'LTESniffer — open-source LTE downlink/uplink eavesdropper (source)' + title: 'LTESniffer: open-source LTE downlink/uplink eavesdropper (source)' authors: SysSec-KAIST venue: GitHub year: 2023 @@ -124,7 +124,7 @@ references: url: 'https://github.com/SysSec-KAIST/LTESniffer/blob/main/pcap_file_example/ltesniffer_dl_mode.pcap' type: tool - key: falcon-repo - title: 'FALCON — Fast Analysis of LTE Control channels (source)' + title: 'FALCON: Fast Analysis of LTE Control channels (source)' authors: 'R. Falkenberg et al. (TU Dortmund)' venue: GitHub year: 2019 @@ -163,17 +163,17 @@ lastResearched: 2026-06-14 LTE multiplexes everything onto an OFDM resource grid: a 10 ms frame of ten 1 ms subframes, each two 0.5 ms slots, carrying QPSK/16/64/256-QAM on downlink OFDMA and uplink SC-FDMA (this control inherits those signal facts from the LTE Wayfinder). Three of those channels are readable by a passive receiver because the network broadcasts them without confidentiality or integrity protection. -The **Physical Downlink Control Channel (PDCCH)** carries Downlink Control Information (DCI) that schedules every transfer. Each DCI is addressed by a Radio Network Temporary Identifier (RNTI) — C-RNTI per active UE, SI-RNTI for system information, P-RNTI for paging, RA-RNTI for random access — and the addressing is implicit: the CRC of the DCI is masked (XORed) with the RNTI. A receiver therefore recovers the control channel by *blind decode*: for each candidate location in the common and UE-specific search spaces it runs the channel decoder and tests whether the CRC, de-masked by a candidate RNTI, checks out. This is exactly what open-source eavesdroppers implement — LTESniffer decodes the PDCCH to obtain the DCIs and RNTIs of all active users, then follows them into the scheduled PDSCH/PUSCH [hoang2023ltesniffer][ltesniffer-repo], and FALCON blind-decodes the entire PDCCH in real time to expose every DCI/RNTI grant in the cell [falcon-repo]. The product is a passive inventory of who is active and how the cell is scheduling them — operational metadata, recovered without transmitting. +The **Physical Downlink Control Channel (PDCCH)** carries Downlink Control Information (DCI) that schedules every transfer. Each DCI is addressed by a Radio Network Temporary Identifier (RNTI), C-RNTI per active UE, SI-RNTI for system information, P-RNTI for paging, RA-RNTI for random access, and the addressing is implicit: the CRC of the DCI is masked (XORed) with the RNTI. A receiver therefore recovers the control channel by *blind decode*: for each candidate location in the common and UE-specific search spaces it runs the channel decoder and tests whether the CRC, de-masked by a candidate RNTI, checks out. This is exactly what open-source eavesdroppers implement, LTESniffer decodes the PDCCH to obtain the DCIs and RNTIs of all active users, then follows them into the scheduled PDSCH/PUSCH [hoang2023ltesniffer][ltesniffer-repo], and FALCON blind-decodes the entire PDCCH in real time to expose every DCI/RNTI grant in the cell [falcon-repo]. The product is a passive inventory of who is active and how the cell is scheduling them, operational metadata, recovered without transmitting. -The **broadcast channels** give the cell's identity: srsUE's cell search locks the PCI from PSS/SSS, decodes the MIB on PBCH for bandwidth and frame number, then reads SIB1 (carried on PDSCH via the SI-RNTI) for the PLMN (MCC+MNC, i.e. the operator), the cell identity and the Tracking Area Code — all in the clear, dissectable in Wireshark over MAC-LTE/GSMTAP. The **paging channel** then leaks per-subscriber activity: paging records normally carry the S-TMSI temporary identifier, and a passive observer who can map that to a target leaks the target's presence in the tracking area. Shaik et al. showed that because the LTE access-network messages (SIBs and paging) are unauthenticated, a low-cost passive/semi-passive attacker can leak a device's presence and coarse location, and that some networks page with the permanent IMSI — a direct identity exposure [shaik2016]. LTrack carried this further, showing the same passive uplink/downlink control-channel decode is sufficient for stealthy phone localisation (using Timing Advance recovered from the control plane) and that a sniffer can bind a UE's TMSI to its IMSI [kotuliak2022ltrack]. +The **broadcast channels** give the cell's identity: srsUE's cell search locks the PCI from PSS/SSS, decodes the MIB on PBCH for bandwidth and frame number, then reads SIB1 (carried on PDSCH via the SI-RNTI) for the PLMN (MCC+MNC, i.e. the operator), the cell identity and the Tracking Area Code, all in the clear, dissectable in Wireshark over MAC-LTE/GSMTAP. The **paging channel** then leaks per-subscriber activity: paging records normally carry the S-TMSI temporary identifier, and a passive observer who can map that to a target leaks the target's presence in the tracking area. Shaik et al. showed that because the LTE access-network messages (SIBs and paging) are unauthenticated, a low-cost passive/semi-passive attacker can leak a device's presence and coarse location, and that some networks page with the permanent IMSI, a direct identity exposure [shaik2016]. LTrack carried this further, showing the same passive uplink/downlink control-channel decode is sufficient for stealthy phone localisation (using Timing Advance recovered from the control plane) and that a sniffer can bind a UE's TMSI to its IMSI [kotuliak2022ltrack]. -The passive view is bounded. EPS-AKA derives the air-interface keys (SNOW 3G / AES / ZUC) from the operator secret on the USIM, so user-plane payloads are not recoverable from a passive capture, and there is no weak-pairing shortcut as in BLE Just Works or WPA2 (a fact this control shares with the LTE Wayfinder CR layer). What passive decode yields is identity, scheduling and configuration exposure, not content. The active and cryptographic attacks that exploit the same procedures and integrity gaps — aLTEr's bit-flipping DNS redirection against the unauthenticated user plane [rupprecht2019alter], ReVoLTE's VoLTE keystream reuse [rupprecht2020revolte], and the authentication-relay / paging-hijack / DoS flaws LTEInspector found in the attach/paging/detach procedures [hussain2018lteinspector] — sit downstream of this passive picture and are scoped by it, but carrying them out requires transmitting and belongs to the Attack layer, not here. +The passive view is bounded. EPS-AKA derives the air-interface keys (SNOW 3G / AES / ZUC) from the operator secret on the USIM, so user-plane payloads are not recoverable from a passive capture, and there is no weak-pairing shortcut as in BLE Just Works or WPA2 (a fact this control shares with the LTE Wayfinder CR layer). What passive decode yields is identity, scheduling and configuration exposure, not content. The active and cryptographic attacks that exploit the same procedures and integrity gaps, aLTEr's bit-flipping DNS redirection against the unauthenticated user plane [rupprecht2019alter], ReVoLTE's VoLTE keystream reuse [rupprecht2020revolte], and the authentication-relay / paging-hijack / DoS flaws LTEInspector found in the attach/paging/detach procedures [hussain2018lteinspector], sit downstream of this passive picture and are scoped by it, but carrying them out requires transmitting and belongs to the Attack layer, not here. The exact number of PDCCH blind-decode candidates a receiver must test per subframe is release- and aggregation-level-dependent (per the search-space definition in 3GPP TS 36.213), so this control deliberately asserts no fixed candidate count; the modulation set (QPSK/16/64/256-QAM) is inherited from the LTE Wayfinder `facts`. ## Procedure -> Authorised testing only. This procedure is **receive-only** — it does not transmit. Even so, receive on licensed cellular spectrum in line with local law and your engagement scope; the goal is to inventory what is exposed, not to interfere. +> Authorised testing only. This procedure is **receive-only**, it does not transmit. Even so, receive on licensed cellular spectrum in line with local law and your engagement scope; the goal is to inventory what is exposed, not to interfere. 1. **Confirm the target carrier first.** You must already know the band/EARFCN and bandwidth (see RFSAM-RES-08 for the identify-and-capture flow). Sanity-check on a waterfall that you are looking at a steady downlink OFDM "wall": ```bash @@ -194,7 +194,7 @@ The exact number of PDCCH blind-decode candidates a receiver must test per subfr ```bash wireshark /tmp/lte_mac.pcap ``` - Filter `mac-lte` / `lte_rrc.SystemInformationBlockType1`. Expected: SIB1 shows the PLMN (MCC+MNC = operator), the cell identity and the TAC — all in the clear. Record them. + Filter `mac-lte` / `lte_rrc.SystemInformationBlockType1`. Expected: SIB1 shows the PLMN (MCC+MNC = operator), the cell identity and the TAC, all in the clear. Record them. 4. **Blind-decode the PDCCH** to enumerate active RNTIs and scheduling. With LTESniffer (downlink mode): ```bash @@ -202,21 +202,21 @@ The exact number of PDCCH blind-decode candidates a receiver must test per subfr ``` Expected: a running list of decoded DCIs with their RNTIs (C-RNTI per active UE, plus SI-/P-/RA-RNTI) and the resource allocations they grant. This is the passive scheduling/activity inventory. FALCON gives an equivalent real-time whole-PDCCH view if you prefer. -5. **Watch the paging channel** for identifier exposure. In the same capture, filter paging in Wireshark (`lte_rrc.PagingRecord` / look for the P-RNTI traffic). Expected: paging records normally carry **S-TMSI** (temporary). Flag any record that pages with **IMSI** (permanent) — that is a direct identity-exposure finding per [shaik2016]. +5. **Watch the paging channel** for identifier exposure. In the same capture, filter paging in Wireshark (`lte_rrc.PagingRecord` / look for the P-RNTI traffic). Expected: paging records normally carry **S-TMSI** (temporary). Flag any record that pages with **IMSI** (permanent), that is a direct identity-exposure finding per [shaik2016]. 6. **Inventory the result.** Record, as the control's finding, exactly which of the following were recoverable purely passively: cell PLMN/identity/TAC (SIB1); the set of active RNTIs and per-subframe scheduling (PDCCH); whether paging used S-TMSI only or ever fell back to IMSI; and whether any unciphered user-plane bearer was observable. The presence of IMSI paging, or of enough scheduling/TMSI continuity to track a known target, is the reportable exposure. ## Field case -Worked against the public downlink sample capture shipped with LTESniffer (SysSec-KAIST/LTESniffer, `pcap_file_example/ltesniffer_dl_mode.pcap`) [ltesniffer-dl-pcap], the data column reads exactly the way this control predicts. The capture is a 2,433-frame, ~`28.6 s` downlink recording (file timestamp 2023-04-25); dissecting it in Wireshark with the MAC-LTE/RRC dissector (USER0/DLT-147 mapped to `mac-lte-framed`) recovers the cell's identity and activity purely passively — no decryption is performed, because none of this is encrypted. +Worked against the public downlink sample capture shipped with LTESniffer (SysSec-KAIST/LTESniffer, `pcap_file_example/ltesniffer_dl_mode.pcap`) [ltesniffer-dl-pcap], the data column reads exactly the way this control predicts. The capture is a 2,433-frame, ~`28.6 s` downlink recording (file timestamp 2023-04-25); dissecting it in Wireshark with the MAC-LTE/RRC dissector (USER0/DLT-147 mapped to `mac-lte-framed`) recovers the cell's identity and activity purely passively, no decryption is performed, because none of this is encrypted. -- The cell broadcasts its identity in the clear in SIB1 (BCCH-DL-SCH, SI-RNTI 65535, SFN 430): PLMN `901-55` (a non-geographic test/shared PLMN, MCC 901 "International Mobile, shared code"), cell identity `0x0019B010` (ECI `105217`, 28-bit), TAC `0x0007`, freqBandIndicator 7 — Band 7. +- The cell broadcasts its identity in the clear in SIB1 (BCCH-DL-SCH, SI-RNTI 65535, SFN 430): PLMN `901-55` (a non-geographic test/shared PLMN, MCC 901 "International Mobile, shared code"), cell identity `0x0019B010` (ECI `105217`, 28-bit), TAC `0x0007`, freqBandIndicator 7, Band 7. - SIB2 reports a `20 MHz` channel: `ul-Bandwidth n100` (100 PRB), with `ul-CarrierFreq` EARFCN 21400 (Band 7 uplink). The downlink channel width follows the same 100-PRB grid. -- The PDCCH/MAC decode over the ~`28.6 s` capture enumerates exactly `one` distinct active C-RNTI (value 70, 642 frames) alongside the broadcast/random-access RNTIs (SI-RNTI 65535 across 1,790 frames; RA-RNTI 2 in 1 frame) — a passive activity inventory of the cell, recovered without transmitting. +- The PDCCH/MAC decode over the ~`28.6 s` capture enumerates exactly `one` distinct active C-RNTI (value 70, 642 frames) alongside the broadcast/random-access RNTIs (SI-RNTI 65535 across 1,790 frames; RA-RNTI 2 in 1 frame), a passive activity inventory of the cell, recovered without transmitting. This is the metadata/identity exposure the control is built to surface: PLMN, ECI, TAC and per-cell scheduling are all readable from a passive downlink capture. The sample capture is downlink-only and contains no paging records that page with IMSI, so it demonstrates the SIB/PDCCH half of the check rather than a permanent-identifier leak. (Per [shaik2016], a network that ever pages with IMSI would convert this into a permanent-identity exposure; per [kotuliak2022ltrack], the same passive decode plus timing-advance is the basis for stealthy localisation.) -The `Found Cell: PCI=[FILL: measured PCI]` line in Step 2 is not asserted from this PCAP — the LTESniffer sample capture carries decoded MAC/RRC frames rather than the raw IQ a live srsUE cell search would lock onto — so the PCI placeholder is kept verbatim for a contributor running the full receive chain against a lab or authorised live cell. +The `Found Cell: PCI=[FILL: measured PCI]` line in Step 2 is not asserted from this PCAP, the LTESniffer sample capture carries decoded MAC/RRC frames rather than the raw IQ a live srsUE cell search would lock onto, so the PCI placeholder is kept verbatim for a contributor running the full receive chain against a lab or authorised live cell. ## Remediation @@ -224,4 +224,4 @@ This is largely a standards/operator concern: passive control-channel and broadc - **Developer (UE / modem stack):** Reject networks that request the permanent identifier (IMSI) in the clear where the configuration allows; honour and prefer operator identity-protection features; do not leak additional stable identifiers above the link that re-enable tracking once the temporary identifier rotates. - **Integrator (network / operator):** Page with S-TMSI, never IMSI; rotate temporary identifiers (S-TMSI/GUTI) frequently to break the continuity a passive observer needs for tracking; minimise sensitive configuration broadcast in SIBs. These are the concrete fixes for the leakage Shaik et al. and LTrack demonstrate [shaik2016][kotuliak2022ltrack]. -- **Operator / programme (defence-in-depth):** Treat the in-the-clear control plane as observable and plan accordingly — deploy false-base-station / cell-site-simulator monitoring (the LTE Wayfinder Attack-layer detectors, e.g. Crocodile Hunter / Rayhunter), and where the threat model warrants it, migrate to 5G. Per 3GPP TS 33.501, 5G conceals the permanent identifier (the SUPI) inside an ECIES-encrypted SUCI sent at initial registration, closing the headline IMSI-in-the-clear exposure that this control documents in LTE — but it does not by itself end all control-plane metadata leakage: paging, temporary-identifier and broadcast behaviour still warrant their own analysis. +- **Operator / programme (defence-in-depth):** Treat the in-the-clear control plane as observable and plan accordingly, deploy false-base-station / cell-site-simulator monitoring (the LTE Wayfinder Attack-layer detectors, e.g. Crocodile Hunter / Rayhunter), and where the threat model warrants it, migrate to 5G. Per 3GPP TS 33.501, 5G conceals the permanent identifier (the SUPI) inside an ECIES-encrypted SUCI sent at initial registration, closing the headline IMSI-in-the-clear exposure that this control documents in LTE, but it does not by itself end all control-plane metadata leakage: paging, temporary-identifier and broadcast behaviour still warrant their own analysis. diff --git a/src/content/controls/rfsam-lte-phy-01.md b/src/content/controls/rfsam-lte-phy-01.md index 426575d..66902f6 100644 --- a/src/content/controls/rfsam-lte-phy-01.md +++ b/src/content/controls/rfsam-lte-phy-01.md @@ -15,7 +15,7 @@ intro: >- LTE's downlink OFDMA physical layer is the wall that stops naive capture: six selectable channel widths up to 1200 subcarriers, a cyclic prefix, and tight symbol/frame timing. This control verifies the receiver can synchronise - on the synchronisation signals and recover the resource grid cleanly — the + on the synchronisation signals and recover the resource grid cleanly, the prerequisite for reading the broadcast/control channels at the Link layer. prerequisites: hardware: @@ -23,7 +23,7 @@ prerequisites: software: - 'srsRAN 4G (cell_search and pdsch_ue example apps), LTESniffer, FALCON, or gr-lte; gqrx for the initial waterfall' signal: - freq: 'Licensed cellular, ~700 MHz–2.6 GHz (full E-UTRA ~450 MHz–3.8 GHz); carrier identified by EARFCN; FDD and TDD' + freq: 'Licensed cellular, ~700 MHz to 2.6 GHz (full E-UTRA ~450 MHz to 3.8 GHz); carrier identified by EARFCN; FDD and TDD' bandwidth: 'One of 1.4, 3, 5, 10, 15, 20 MHz' modulation: 'Downlink OFDMA, QPSK/16/64/256-QAM; 10 ms frame → 10 subframes (1 ms) → 2 slots (0.5 ms)' skill: advanced @@ -58,14 +58,14 @@ references: url: 'https://doi.org/10.1145/3558482.3590196' type: paper - key: srsran4g - title: srsRAN 4G — open-source SDR 4G suite (srsUE cell_search / pdsch_ue) + title: srsRAN 4G, open-source SDR 4G suite (srsUE cell_search / pdsch_ue) authors: Software Radio Systems venue: GitHub year: 2024 url: 'https://github.com/srsran/srsRAN_4G' type: tool - key: grlte - title: gr-lte — GNU Radio LTE receiver flowgraph (sync, channel estimation, PBCH) + title: gr-lte, GNU Radio LTE receiver flowgraph (sync, channel estimation, PBCH) authors: KIT Communications Engineering Lab venue: GitHub year: 2020 @@ -89,15 +89,15 @@ lastResearched: 2026-06-14 --- ## Mechanism -The LTE downlink is OFDMA: the carrier is divided into 15 kHz subcarriers grouped into resource blocks of 12 subcarriers, and a symbol plus its cyclic prefix occupies the time–frequency *resource grid*. A 20 MHz carrier carries 100 resource blocks (1200 subcarriers); the smallest, 1.4 MHz, carries 6 (72 subcarriers). Time is structured as a 10 ms radio frame of ten 1 ms subframes, each two 0.5 ms slots [[ts36211]]. Recovering anything above the antenna therefore means first reconstructing this grid — which is exactly where capture coherence matters: a free-running SDR clock drifts in frequency and time, rotating and smearing the QAM constellation on each subcarrier until the grid is unreadable. A disciplined reference (a GPSDO or equivalent) supplies the stable frequency/timing that keeps the subcarriers aligned (RFSAM-RES-09). +The LTE downlink is OFDMA: the carrier is divided into 15 kHz subcarriers grouped into resource blocks of 12 subcarriers, and a symbol plus its cyclic prefix occupies the time-frequency *resource grid*. A 20 MHz carrier carries 100 resource blocks (1200 subcarriers); the smallest, 1.4 MHz, carries 6 (72 subcarriers). Time is structured as a 10 ms radio frame of ten 1 ms subframes, each two 0.5 ms slots [[ts36211]]. Recovering anything above the antenna therefore means first reconstructing this grid, which is exactly where capture coherence matters: a free-running SDR clock drifts in frequency and time, rotating and smearing the QAM constellation on each subcarrier until the grid is unreadable. A disciplined reference (a GPSDO or equivalent) supplies the stable frequency/timing that keeps the subcarriers aligned (RFSAM-RES-09). -Synchronisation is bootstrapped from two signals the cell always transmits in the centre 62 subcarriers, independent of bandwidth. The Primary Synchronisation Signal (PSS) gives symbol timing and N_ID(2) ∈ {0,1,2}; the Secondary Synchronisation Signal (SSS) gives N_ID(1) ∈ {0..167} and frame timing. The Physical Cell ID is then PCI = 3·N_ID(1) + N_ID(2), one of 504 values [[ts36211]]. Once PSS/SSS are locked, the Physical Broadcast Channel (PBCH) around the centre carries the Master Information Block (MIB), which states the system bandwidth, PHICH configuration, and the System Frame Number — the bandwidth value is what tells the receiver how wide the rest of the grid actually is [[ts36211]]. With bandwidth known, the control region (PDCCH) and shared channel (PDSCH) of each subframe can be demapped. +Synchronisation is bootstrapped from two signals the cell always transmits in the centre 62 subcarriers, independent of bandwidth. The Primary Synchronisation Signal (PSS) gives symbol timing and N_ID(2) ∈ {0,1,2}; the Secondary Synchronisation Signal (SSS) gives N_ID(1) ∈ {0..167} and frame timing. The Physical Cell ID is then PCI = 3·N_ID(1) + N_ID(2), one of 504 values [[ts36211]]. Once PSS/SSS are locked, the Physical Broadcast Channel (PBCH) around the centre carries the Master Information Block (MIB), which states the system bandwidth, PHICH configuration, and the System Frame Number, the bandwidth value is what tells the receiver how wide the rest of the grid actually is [[ts36211]]. With bandwidth known, the control region (PDCCH) and shared channel (PDSCH) of each subframe can be demapped. -The open-source LTE-receiver lineage establishes that this full chain — PSS/SSS sync, PCI, MIB on PBCH, then blind PDCCH and PDSCH decode — is reproducible on commodity SDRs, and that decode reliability is gated by capture quality and clock discipline rather than by any secret. OWL grounds reliable control-channel decoding on information from the random-access procedure and reports decoding the resource grid in over 99% of frames on inexpensive SDR hardware [[bui2016owl]]. FALCON blind-decodes the whole PDCCH (the DCI/RNTI scheduling grants in the cell) in real time and is an alternative to OWL that is less sensitive to non-ideal radio conditions [[falkenberg2019falcon]]. LTESniffer chains PDCCH → PDSCH/PUSCH to passively recover downlink and uplink scheduling and traffic, and documents that uplink capture across two USRP B-series units requires a GPSDO for inter-unit synchronisation — concrete evidence that grid recovery is coherence-bound [[hoang2023ltesniffer]]. This control verifies only the capture-feasibility prerequisite (sync + grid recovery); it is observational and reads what the network already broadcasts, so its criticality is `info`. Reading the broadcast/control information itself, and any active step, belong to the Link and Attack layers. +The open-source LTE-receiver lineage establishes that this full chain, PSS/SSS sync, PCI, MIB on PBCH, then blind PDCCH and PDSCH decode, is reproducible on commodity SDRs, and that decode reliability is gated by capture quality and clock discipline rather than by any secret. OWL grounds reliable control-channel decoding on information from the random-access procedure and reports decoding the resource grid in over 99% of frames on inexpensive SDR hardware [[bui2016owl]]. FALCON blind-decodes the whole PDCCH (the DCI/RNTI scheduling grants in the cell) in real time and is an alternative to OWL that is less sensitive to non-ideal radio conditions [[falkenberg2019falcon]]. LTESniffer chains PDCCH → PDSCH/PUSCH to passively recover downlink and uplink scheduling and traffic, and documents that uplink capture across two USRP B-series units requires a GPSDO for inter-unit synchronisation, concrete evidence that grid recovery is coherence-bound [[hoang2023ltesniffer]]. This control verifies only the capture-feasibility prerequisite (sync + grid recovery); it is observational and reads what the network already broadcasts, so its criticality is `info`. Reading the broadcast/control information itself, and any active step, belong to the Link and Attack layers. ## Procedure -All steps below are passive reception only. LTE is licensed spectrum: receiving a downlink is generally permissible, but treat local regulation as authoritative, and never transmit on an operator's band — any active step (rogue cell, identity request) is a separate Attack-layer control and is for authorised testing on your own equipment in RF containment. +All steps below are passive reception only. LTE is licensed spectrum: receiving a downlink is generally permissible, but treat local regulation as authoritative, and never transmit on an operator's band, any active step (rogue cell, identity request) is a separate Attack-layer control and is for authorised testing on your own equipment in RF containment. 1. **Confirm a disciplined reference and a healthy receiver.** Lock the SDR to its GPSDO (or an external 10 MHz reference) and confirm it initialises before relying on the capture (RFSAM-RES-09). With UHD/USRP: ```bash @@ -105,7 +105,7 @@ All steps below are passive reception only. LTE is licensed spectrum: receiving ``` Expect the probe to enumerate the AD9361 daughterboard and report the reference source as locked. A free-running clock still captures, but report capture quality as a limiting factor for the control region. -2. **Find the carrier and read its width on a waterfall.** Sweep the candidate bands in gqrx and identify the steady OFDM "wall" of a downlink carrier; note its centre frequency (→ EARFCN) and visible width (1.4–20 MHz). A 20 MHz carrier fits in one HackRF view; a wider, disciplined SDR gives cleaner symbols later (RFSAM-RES-08). +2. **Find the carrier and read its width on a waterfall.** Sweep the candidate bands in gqrx and identify the steady OFDM "wall" of a downlink carrier; note its centre frequency (→ EARFCN) and visible width (1.4 to 20 MHz). A 20 MHz carrier fits in one HackRF view; a wider, disciplined SDR gives cleaner symbols later (RFSAM-RES-08). 3. **Run cell search to recover the PCI from PSS/SSS.** With srsRAN's `cell_search` example, scan a band (here band 3, ~1800 MHz): ```bash @@ -115,7 +115,7 @@ All steps below are passive reception only. LTE is licensed spectrum: receiving ``` Found CELL 1845.0 MHz, EARFCN=1500, PHYID=123, 100 PRB, 1 ports, PSS power=-65.0 dBm ``` - `PHYID` is the PCI (0–503), `nof PRB` confirms the bandwidth recovered from PBCH, and a sane `PSS power` indicates a clean lock. No "Found CELL" line means sync failed — revisit gain, centre frequency, or clock discipline. + `PHYID` is the PCI (0 to 503), `nof PRB` confirms the bandwidth recovered from PBCH, and a sane `PSS power` indicates a clean lock. No "Found CELL" line means sync failed, revisit gain, centre frequency, or clock discipline. 4. **Decode the MIB and demodulate the grid on the chosen carrier.** Point the `pdsch_ue` example at the carrier (use the EARFCN's RX frequency from step 3): ```bash @@ -138,16 +138,16 @@ All steps below are passive reception only. LTE is licensed spectrum: receiving ## Field case -Illustrative walkthrough — substitute the values you capture; this is a reproducible example, not a measured engagement, and every unmeasured quantity is marked `[FILL: …]`. +Illustrative walkthrough, substitute the values you capture; this is a reproducible example, not a measured engagement, and every unmeasured quantity is marked `[FILL: …]`. -Rig: a USRP B210 with the GPSDO option, fed a band-3 (1800 MHz FDD) downlink. After `uhd_usrp_probe` confirms the GPSDO reference, `cell_search -b 3` returns a `Found CELL` line reporting `EARFCN=[FILL: e.g. 1500]`, `PHYID=[FILL: PCI 0–503]`, `[FILL: nof] PRB`, and `PSS power=[FILL: dBm]`. Pointing `pdsch_ue -f [FILL: RX Hz] -A 2` at that carrier produces a steady `Decoded MIB. SFN: [FILL]` and, at subframe 5, `PDCCH-Miss: [FILL: %]` / `PDSCH-BLER: [FILL: %]`. The control passes when synchronisation holds, the PCI is stable across repeated runs, and the grid demodulates without timing-induced corruption. +Rig: a USRP B210 with the GPSDO option, fed a band-3 (1800 MHz FDD) downlink. After `uhd_usrp_probe` confirms the GPSDO reference, `cell_search -b 3` returns a `Found CELL` line reporting `EARFCN=[FILL: e.g. 1500]`, `PHYID=[FILL: PCI 0 to 503]`, `[FILL: nof] PRB`, and `PSS power=[FILL: dBm]`. Pointing `pdsch_ue -f [FILL: RX Hz] -A 2` at that carrier produces a steady `Decoded MIB. SFN: [FILL]` and, at subframe 5, `PDCCH-Miss: [FILL: %]` / `PDSCH-BLER: [FILL: %]`. The control passes when synchronisation holds, the PCI is stable across repeated runs, and the grid demodulates without timing-induced corruption. -A documented degradation pattern worth reproducing: the *same* recorded carrier that decoded MIB cleanly on a desktop host failed intermittently on an underpowered mini-PC — the SDR was fine, but host I/O could not sustain the sample rate, surfacing as `Cell not found` retries and elevated PDCCH-Miss. This is the practical lesson of RFSAM-RES-09: coherent OFDM capture is bounded by the *whole* chain (reference clock and host throughput), not the radio alone. +A documented degradation pattern worth reproducing: the *same* recorded carrier that decoded MIB cleanly on a desktop host failed intermittently on an underpowered mini-PC, the SDR was fine, but host I/O could not sustain the sample rate, surfacing as `Cell not found` retries and elevated PDCCH-Miss. This is the practical lesson of RFSAM-RES-09: coherent OFDM capture is bounded by the *whole* chain (reference clock and host throughput), not the radio alone. ## Remediation This is an auditor-side capture-quality control; "remediation" is mostly about reporting accurately, but the layered guidance still applies to the systems being assessed. - **Auditor (capture chain):** Use a disciplined reference (GPSDO or external 10 MHz) for any OFDM capture and validate the host can sustain the sample rate before drawing conclusions (RFSAM-RES-08, RFSAM-RES-09). If sync is marginal, report capture quality as a limiting factor rather than asserting a clean negative result. -- **Developer / network integrator:** The information recovered by this control — PCI, system bandwidth, MIB/SFN, and the PDCCH scheduling picture — is broadcast or sent in the clear by design and *cannot* be hidden at the PHY layer [[ts36211]][[bui2016owl]]. Do not treat broadcast obscurity as a security boundary. Real protections live above the air interface: enable user-plane ciphering and integrity per bearer, and ensure identity privacy (S-TMSI rather than IMSI on paging) so that easy grid recovery does not translate into easy tracking. +- **Developer / network integrator:** The information recovered by this control, PCI, system bandwidth, MIB/SFN, and the PDCCH scheduling picture, is broadcast or sent in the clear by design and *cannot* be hidden at the PHY layer [[ts36211]][[bui2016owl]]. Do not treat broadcast obscurity as a security boundary. Real protections live above the air interface: enable user-plane ciphering and integrity per bearer, and ensure identity privacy (S-TMSI rather than IMSI on paging) so that easy grid recovery does not translate into easy tracking. - **Operator:** Recognise that passive resource-grid recovery and PDCCH monitoring are inexpensive and well-documented [[falkenberg2019falcon]][[hoang2023ltesniffer]]; treat the control plane visible from the air as observable, and base detection of rogue-infrastructure and tracking on the Attack-layer controls rather than assuming the PHY layer is private. diff --git a/src/content/controls/rfsam-lte-sp-01.md b/src/content/controls/rfsam-lte-sp-01.md index fb6f5d3..634a78d 100644 --- a/src/content/controls/rfsam-lte-sp-01.md +++ b/src/content/controls/rfsam-lte-sp-01.md @@ -10,26 +10,26 @@ deferred: false objective: >- Establish which operator, band, downlink EARFCN and Physical Cell ID (PCI) are present in the environment, and confirm each target cell falls inside the - receiver's tuning and capture envelope — the spectrum-layer prerequisite that + receiver's tuning and capture envelope, the spectrum-layer prerequisite that scopes every later LTE control. intro: >- LTE lives in narrow licensed slices scattered from roughly 700 MHz to 2.6 GHz, - and a carrier is 1.4–20 MHz wide. Before any capture is meaningful you must find + and a carrier is 1.4 to 20 MHz wide. Before any capture is meaningful you must find the downlink carrier and read its centre frequency (EARFCN) and width, then - identify the cell — operator (PLMN), band and PCI. This control records that + identify the cell, operator (PLMN), band and PCI. This control records that operator/band/EARFCN/PCI inventory; it is an environmental baseline, not a device finding. Receiving broadcast information is passive, but anything that transmits is for authorised testing only. prerequisites: hardware: - - 'A receive SDR that covers the target band: HackRF One (1 MHz–6 GHz, ~20 MHz IBW) or USRP B210/bladeRF 2.0 for wide carriers; an RTL-SDR Blog V4 reaches only the low bands (stops near 1.766 GHz, below the 1.8–2.6 GHz carriers)' + - 'A receive SDR that covers the target band: HackRF One (1 MHz to 6 GHz, ~20 MHz IBW) or USRP B210/bladeRF 2.0 for wide carriers; an RTL-SDR Blog V4 reaches only the low bands (stops near 1.766 GHz, below the 1.8 to 2.6 GHz carriers)' - 'Optionally a commercial Qualcomm-based LTE modem (SIMCom SIM7600) with a valid/test SIM, for a no-SDR serving-cell read over AT commands' software: - 'gqrx for the live spectrum/waterfall view' - 'srsRAN 4G (srsue) for PSS/SSS cell search → PCI, MIB and SIB1 decode' - 'An AT terminal (and optionally QCSuper) for the modem route' signal: - freq: 'Licensed cellular, common bands ~700 MHz–2.6 GHz (full E-UTRA set ~450 MHz–3.8 GHz); FDD and TDD' + freq: 'Licensed cellular, common bands ~700 MHz to 2.6 GHz (full E-UTRA set ~450 MHz to 3.8 GHz); FDD and TDD' bandwidth: 'Six channel widths: 1.4, 3, 5, 10, 15, 20 MHz; the carrier is identified by its EARFCN' modulation: 'Downlink OFDMA, uplink SC-FDMA; QPSK/16/64/256-QAM; 10 ms frame → 10 subframes' skill: intermediate @@ -38,8 +38,8 @@ attacks: refs: - shaik2016lte impact: >- - The same passive identity reconnaissance — PCI, EARFCN, PLMN, TAC and the - in-the-clear SIB configuration — is the first step an IMSI catcher or + The same passive identity reconnaissance, PCI, EARFCN, PLMN, TAC and the + in-the-clear SIB configuration, is the first step an IMSI catcher or fake-eNodeB operator performs to mimic a legitimate cell and lure a target UE; reading it is observation, but it is also the attacker's setup phase. preconditions: >- @@ -52,17 +52,17 @@ attacks: base stations and LTE IMSI catchers. references: - key: ts36211 - title: '3GPP TS 36.211 — E-UTRA; Physical channels and modulation (PSS/SSS, PCI, OFDMA)' + title: '3GPP TS 36.211: E-UTRA; Physical channels and modulation (PSS/SSS, PCI, OFDMA)' venue: 3GPP url: 'https://portal.3gpp.org/desktopmodules/Specifications/SpecificationDetails.aspx?specificationId=2425' type: standard - key: ts36101 - title: '3GPP TS 36.101 — E-UTRA; UE radio transmission and reception (operating bands, EARFCN)' + title: '3GPP TS 36.101: E-UTRA; UE radio transmission and reception (operating bands, EARFCN)' venue: 3GPP url: 'https://portal.3gpp.org/desktopmodules/Specifications/SpecificationDetails.aspx?specificationId=2411' type: standard - key: ts36331 - title: '3GPP TS 36.331 — E-UTRA; Radio Resource Control (RRC) protocol (MIB, SIB1: PLMN, cell ID, TAC)' + title: '3GPP TS 36.331: E-UTRA; Radio Resource Control (RRC) protocol (MIB, SIB1: PLMN, cell ID, TAC)' venue: 3GPP url: 'https://portal.3gpp.org/desktopmodules/Specifications/SpecificationDetails.aspx?specificationId=2440' type: standard @@ -74,13 +74,13 @@ references: url: 'https://arxiv.org/abs/1510.07563' type: paper - key: srsran4g - title: 'srsRAN 4G — open-source SDR 4G suite (srsUE cell search, MIB/SIB receiver, MAC-LTE/RRC pcap)' + title: 'srsRAN 4G: open-source SDR 4G suite (srsUE cell search, MIB/SIB receiver, MAC-LTE/RRC pcap)' authors: Software Radio Systems (SRS) venue: GitHub url: 'https://github.com/srsran/srsRAN_4G' type: tool - key: qcsuper - title: 'QCSuper — capture raw 2G/3G/4G radio frames from Qualcomm modems via the Diag port' + title: 'QCSuper: capture raw 2G/3G/4G radio frames from Qualcomm modems via the Diag port' authors: P1 Security venue: GitHub url: 'https://github.com/P1sec/QCSuper' @@ -101,24 +101,24 @@ lastResearched: 2026-06-14 --- ## Mechanism -An LTE deployment is a grid of cells. Each cell transmits on a downlink carrier identified by its EARFCN (E-UTRA Absolute Radio Frequency Channel Number), and the EARFCN-to-frequency mapping and the set of operating bands are defined in 3GPP TS 36.101 [ts36101]. A carrier occupies one of six channel widths — 1.4, 3, 5, 10, 15 or 20 MHz — and the downlink is OFDMA, so on a waterfall it appears as a steady, flat "wall" of energy whose width tells you the channel bandwidth [ts36211]. Because the carrier sits in licensed spectrum, with the most common deployed bands scattered from roughly 700 MHz to 2.6 GHz (the full E-UTRA operating-band set defined in TS 36.101 extends wider still — from the ~450 MHz low bands up into the 3.x GHz range), which SDR can even tune it is a hard constraint: an RTL-SDR Blog V4 stops near 1.766 GHz and cannot reach the 1.8–2.6 GHz carriers, while a HackRF or USRP/bladeRF reaches the full set [ts36101]. +An LTE deployment is a grid of cells. Each cell transmits on a downlink carrier identified by its EARFCN (E-UTRA Absolute Radio Frequency Channel Number), and the EARFCN-to-frequency mapping and the set of operating bands are defined in 3GPP TS 36.101 [ts36101]. A carrier occupies one of six channel widths, 1.4, 3, 5, 10, 15 or 20 MHz, and the downlink is OFDMA, so on a waterfall it appears as a steady, flat "wall" of energy whose width tells you the channel bandwidth [ts36211]. Because the carrier sits in licensed spectrum, with the most common deployed bands scattered from roughly 700 MHz to 2.6 GHz (the full E-UTRA operating-band set defined in TS 36.101 extends wider still, from the ~450 MHz low bands up into the 3.x GHz range), which SDR can even tune it is a hard constraint: an RTL-SDR Blog V4 stops near 1.766 GHz and cannot reach the 1.8 to 2.6 GHz carriers, while a HackRF or USRP/bladeRF reaches the full set [ts36101]. -Once the carrier is found, the cell identifies itself in the clear. The Primary and Secondary Synchronisation Signals (PSS/SSS) on the centre subcarriers give the Physical Cell ID: PSS yields N_ID(2) (0–2), SSS yields N_ID(1) (0–167), and PCI = 3·N_ID(1) + N_ID(2), so 504 PCIs (0–503) exist [ts36211]. The Master Information Block (MIB) on the PBCH then carries the system bandwidth and frame number, and System Information Block 1 (SIB1) carries the operator identity (PLMN = MCC+MNC), the cell identity and the Tracking Area Code (TAC) [ts36331]. None of this is encrypted — synchronisation, MIB and SIB are broadcast unprotected by design, so any receiver in range reads the cell's identity without a credential [ts36211][ts36331]. +Once the carrier is found, the cell identifies itself in the clear. The Primary and Secondary Synchronisation Signals (PSS/SSS) on the centre subcarriers give the Physical Cell ID: PSS yields N_ID(2) (0 to 2), SSS yields N_ID(1) (0 to 167), and PCI = 3·N_ID(1) + N_ID(2), so 504 PCIs (0 to 503) exist [ts36211]. The Master Information Block (MIB) on the PBCH then carries the system bandwidth and frame number, and System Information Block 1 (SIB1) carries the operator identity (PLMN = MCC+MNC), the cell identity and the Tracking Area Code (TAC) [ts36331]. None of this is encrypted, synchronisation, MIB and SIB are broadcast unprotected by design, so any receiver in range reads the cell's identity without a credential [ts36211][ts36331]. -That same unprotected broadcast and pre-authentication information is what an attacker exploits: Shaik et al. demonstrate that low-cost fake base stations and LTE IMSI catchers begin by reading exactly this PCI/EARFCN/PLMN/SIB configuration so they can mimic a legitimate cell and lure a target UE [shaik2016lte]. Performing this inventory passively is therefore both the auditor's scoping step and a mirror of the attacker's reconnaissance phase. This control owns the spectrum-layer half — find the carrier and read the cell identity; the deeper control-channel and broadcast decode is the work of the LTE capture controls. +That same unprotected broadcast and pre-authentication information is what an attacker exploits: Shaik et al. demonstrate that low-cost fake base stations and LTE IMSI catchers begin by reading exactly this PCI/EARFCN/PLMN/SIB configuration so they can mimic a legitimate cell and lure a target UE [shaik2016lte]. Performing this inventory passively is therefore both the auditor's scoping step and a mirror of the attacker's reconnaissance phase. This control owns the spectrum-layer half, find the carrier and read the cell identity; the deeper control-channel and broadcast decode is the work of the LTE capture controls. ## Procedure -> Authorised testing only. Every step below is receive-only — you read what the +> Authorised testing only. Every step below is receive-only, you read what the > network already broadcasts. Do not transmit on licensed cellular spectrum. -1. **Scope the candidate bands and confirm your radio reaches them.** Decide which bands are plausible for the operators in your region (for example B28/700 MHz, B20/800 MHz, B3/1800 MHz, B7/2.6 GHz). If you are using an RTL-SDR V4, restrict yourself to the low bands — it cannot tune the 1.8–2.6 GHz carriers [ts36101]. +1. **Scope the candidate bands and confirm your radio reaches them.** Decide which bands are plausible for the operators in your region (for example B28/700 MHz, B20/800 MHz, B3/1800 MHz, B7/2.6 GHz). If you are using an RTL-SDR V4, restrict yourself to the low bands, it cannot tune the 1.8 to 2.6 GHz carriers [ts36101]. 2. **Find the downlink carrier on a waterfall** with gqrx. Tune across the candidate band and look for the steady OFDM "wall": ```bash gqrx ``` - In the GUI, set the device to your SDR, tune to a candidate downlink centre and watch the waterfall. A live LTE downlink shows as a flat, continuous block; read its centre frequency and estimate its width (e.g. ~20 MHz). Record the centre frequency — this is the carrier you will map to an EARFCN [ts36211]. + In the GUI, set the device to your SDR, tune to a candidate downlink centre and watch the waterfall. A live LTE downlink shows as a flat, continuous block; read its centre frequency and estimate its width (e.g. ~20 MHz). Record the centre frequency, this is the carrier you will map to an EARFCN [ts36211]. 3. **Run a cell search to recover PCI, MIB and SIB1** with srsRAN's `srsue` against the carrier you found. Cell search synchronises on PSS/SSS to get the PCI, then decodes the MIB and SIB1: ```bash @@ -126,26 +126,26 @@ That same unprotected broadcast and pre-authentication information is what an at ``` In the srsUE log you should see lines reporting the found cell, for example: `Found Cell: PCI=, PRB=, Ports=, CFO=...` followed by MIB decode (bandwidth, SFN) and, once attached/sniffing, SIB1 contents (PLMN, cell ID, TAC). A non-zero PCI and a decoded MIB confirm the carrier and identity [srsran4g][ts36211][ts36331]. -4. **(No-SDR cross-check) Read the serving cell from a commercial modem.** A Qualcomm-based SIM7600 reports its serving cell over AT commands — the fastest way to confirm which cell a target is camped on: +4. **(No-SDR cross-check) Read the serving cell from a commercial modem.** A Qualcomm-based SIM7600 reports its serving cell over AT commands, the fastest way to confirm which cell a target is camped on: ```text AT+CPSI? ``` - Per the SIMCom AT command manual the LTE read returns `LTE,,-,,,,,,,,...` — i.e. operator, Tracking Area Code, serving-cell ID, PCI, band and EARFCN on one line, e.g. `+CPSI: LTE,Online,-,0x,,,EUTRAN-BAND,,...`. For a deeper, still-passive read of the broadcast/paging the modem already receives, stream its Diag port into Wireshark with QCSuper [qcsuper]. + Per the SIMCom AT command manual the LTE read returns `LTE,,-,,,,,,,...`, i.e. operator, Tracking Area Code, serving-cell ID, PCI, band and EARFCN on one line, e.g. `+CPSI: LTE,Online,-,0x,,,EUTRAN-BAND,...`. For a deeper, still-passive read of the broadcast/paging the modem already receives, stream its Diag port into Wireshark with QCSuper [qcsuper]. -5. **Record the inventory.** For each cell, capture: operator (PLMN MCC-MNC), band, downlink EARFCN, PCI, system bandwidth and TAC. Mark which cells fall inside your SDR's tuning and instantaneous-bandwidth envelope — those are the sniffable targets that scope the later LTE capture controls (RFSAM-RES-08). +5. **Record the inventory.** For each cell, capture: operator (PLMN MCC-MNC), band, downlink EARFCN, PCI, system bandwidth and TAC. Mark which cells fall inside your SDR's tuning and instantaneous-bandwidth envelope, those are the sniffable targets that scope the later LTE capture controls (RFSAM-RES-08). ## Field case -A scan in Mexico surfaced 5 cells, 4 of them sniffable: Telcel on B4/B66/B5 and AT&T on B2, with real PCIs (58 / 287 / 301) and measured EARFCNs. Knowing operator, band and EARFCN is the prerequisite — without it, capture is aimed at nothing. +A scan in Mexico surfaced 5 cells, 4 of them sniffable: Telcel on B4/B66/B5 and AT&T on B2, with real PCIs (58 / 287 / 301) and measured EARFCNs. Knowing operator, band and EARFCN is the prerequisite, without it, capture is aimed at nothing. -That inventory is exactly what the procedure above produces and what scopes the later LTE capture controls: one of those cells (the B4 Telcel cell, PCI 58) sits well inside a HackRF's tuning and instantaneous-bandwidth envelope, so it is a viable capture target; the AT&T B2 cell at ~1.9 GHz is reachable by a HackRF/USRP but not by an RTL-SDR V4. The full SIB1 fields for the PCI-58 cell — PLMN, cell ID, TAC — were [FILL: not captured to the report in this baseline; record from the srsUE SIB1 decode when reproducing]. +That inventory is exactly what the procedure above produces and what scopes the later LTE capture controls: one of those cells (the B4 Telcel cell, PCI 58) sits well inside a HackRF's tuning and instantaneous-bandwidth envelope, so it is a viable capture target; the AT&T B2 cell at ~1.9 GHz is reachable by a HackRF/USRP but not by an RTL-SDR V4. The full SIB1 fields for the PCI-58 cell, PLMN, cell ID, TAC, were [FILL: not captured to the report in this baseline; record from the srsUE SIB1 decode when reproducing]. ## Remediation -This is an environmental baseline and target-selection step, not a device defect — the "weakness" it surfaces is inherent to LTE's unprotected broadcast design [ts36211][ts36331]. Layered guidance for what *can* be hardened: +This is an environmental baseline and target-selection step, not a device defect, the "weakness" it surfaces is inherent to LTE's unprotected broadcast design [ts36211][ts36331]. Layered guidance for what *can* be hardened: -- **Network operator** — you cannot encrypt PSS/SSS/MIB/SIB1, but you can minimise what the *clear* identifiers leak: prefer S-TMSI over IMSI on the paging channel and avoid IMSI paging where possible, and monitor for anomalous PCIs/EARFCNs/SIB configurations that indicate a fake cell mimicking your network [shaik2016lte]. Where the network supports it, enable false-base-station mitigations and consistency checks on broadcast information. +- **Network operator**, you cannot encrypt PSS/SSS/MIB/SIB1, but you can minimise what the *clear* identifiers leak: prefer S-TMSI over IMSI on the paging channel and avoid IMSI paging where possible, and monitor for anomalous PCIs/EARFCNs/SIB configurations that indicate a fake cell mimicking your network [shaik2016lte]. Where the network supports it, enable false-base-station mitigations and consistency checks on broadcast information. -- **Device integrator** — select basebands/modems that implement fake-base-station detection and that resist downgrade/redirection driven from a rogue cell's broadcast; expose modem diagnostics (e.g. the Diag interface) only to authorised tooling, since the same passive read this control performs is also an attacker's reconnaissance feed [shaik2016lte]. +- **Device integrator**, select basebands/modems that implement fake-base-station detection and that resist downgrade/redirection driven from a rogue cell's broadcast; expose modem diagnostics (e.g. the Diag interface) only to authorised tooling, since the same passive read this control performs is also an attacker's reconnaissance feed [shaik2016lte]. -- **Auditor / operator of the test** — keep this step strictly receive-only; do not transmit on licensed spectrum. Treat the operator/band/EARFCN/PCI inventory as scoping data for the assessment, and confirm each target cell is inside your receiver's tuning and bandwidth envelope before committing capture hardware (RFSAM-RES-08). +- **Auditor / operator of the test**, keep this step strictly receive-only; do not transmit on licensed spectrum. Treat the operator/band/EARFCN/PCI inventory as scoping data for the assessment, and confirm each target cell is inside your receiver's tuning and bandwidth envelope before committing capture hardware (RFSAM-RES-08). diff --git a/src/content/controls/rfsam-nr5g-ll-01.md b/src/content/controls/rfsam-nr5g-ll-01.md index 3c4fac0..1a7fa44 100644 --- a/src/content/controls/rfsam-nr5g-ll-01.md +++ b/src/content/controls/rfsam-nr5g-ll-01.md @@ -11,29 +11,29 @@ applicability: deferred: false objective: >- Determine, from a purely passive capture, which identity and configuration - data a 5G NR cell exposes on its broadcast channels — cell configuration from + data a 5G NR cell exposes on its broadcast channels, cell configuration from the MIB (PBCH) and SIB1 (PLMN, cell identity, TAC), and the form of the - subscriber's long-term identifier on the air — and confirm whether the + subscriber's long-term identifier on the air, and confirm whether the subscriber identity is concealed as a SUCI (and under which protection scheme) or sent effectively in the clear via the null-scheme. intro: >- 5G broadcasts its cell configuration (MIB, SIB1) in the clear, exactly as LTE does, but improves on the subscriber-identity exposure: the long-term identity (SUPI/IMSI) is concealed as a SUCI before it leaves the device. This control - inventories what the broadcast channels actually expose — cell identity and + inventories what the broadcast channels actually expose, cell identity and tracking-area configuration that remain in the clear, and whether the SUCI is genuinely encrypted or falls back to the null-scheme that re-opens the LTE-style permanent-identity leak. prerequisites: hardware: - - 'A coherent, ideally GPSDO-disciplined SDR for clean CP-OFDM grid recovery: USRP B210 (preferred), bladeRF 2.0 micro, or SignalSDR Pro; FR1 sub-6 GHz only (FR2 mmWave ~24–52 GHz is out of reach of these tuners)' + - 'A coherent, ideally GPSDO-disciplined SDR for clean CP-OFDM grid recovery: USRP B210 (preferred), bladeRF 2.0 micro, or SignalSDR Pro; FR1 sub-6 GHz only (FR2 mmWave ~24 to 52 GHz is out of reach of these tuners)' - 'Or, the no-SDR route: a Qualcomm-based 5G modem exposing the DIAG interface (e.g. Quectel RM500Q) with a registered/test SIM, read passively with QCSuper' software: - '5GSniffer (passive PDCCH/DCI blind decoder), or Sni5Gect (research MAC-NR over-the-air sniffer); srsRAN Project to stand up a controlled SA cell when no turnkey passive SA receiver exists; QCSuper for the modem DIAG route; Wireshark for MAC-NR / NGAP / NAS-5GS dissection' signal: - freq: 'Licensed cellular FR1 ~410 MHz–7.125 GHz (common bands n1/2100, n3/1800, n78/3.5 GHz TDD, n28/700); the NR-ARFCN/band must be known first' + freq: 'Licensed cellular FR1 ~410 MHz to 7.125 GHz (common bands n1/2100, n3/1800, n78/3.5 GHz TDD, n28/700); the NR-ARFCN/band must be known first' bandwidth: 'Flexible numerology, subcarrier spacing 15·2^μ kHz (15/30/60/120 kHz); a carrier reaches up to 100 MHz in FR1, wider than a single HackRF (~20 MHz) or B210 (~56 MHz) view' - modulation: 'CP-OFDM downlink and uplink (uplink may also use DFT-s-OFDM); QPSK/16/64/256-QAM. PSS/SSS in the SS/PBCH block (SSB) → PCI = 3·N_ID(1) + N_ID(2) (0–1007)' + modulation: 'CP-OFDM downlink and uplink (uplink may also use DFT-s-OFDM); QPSK/16/64/256-QAM. PSS/SSS in the SS/PBCH block (SSB) → PCI = 3·N_ID(1) + N_ID(2) (0 to 1007)' skill: advanced attacks: - name: SUCI-catcher (null-scheme exposure and AKA-based linkability) @@ -54,7 +54,7 @@ attacks: summary: >- The SUCI conceals the permanent identity in the common case, but the null-scheme fallback exposes the SUPI in the clear and the AKA procedure - still permits linkability — so a 5G "SUCI-catcher" remains possible under + still permits linkability, so a 5G "SUCI-catcher" remains possible under specific conditions. - name: Unauthenticated broadcast trust (fake-cell / pre-authentication surface) refs: @@ -63,7 +63,7 @@ attacks: impact: >- Because the MIB/SIB broadcast and pre-authentication RRC/NAS messages carry no source authentication, a UE has no way to validate the configuration it - reads on first contact — the foundation a rogue gNB stands on to drive + reads on first contact, the foundation a rogue gNB stands on to drive registration/identity exchanges, downgrades, and warning-message spoofing/suppression. preconditions: >- @@ -104,14 +104,14 @@ references: url: 'https://arxiv.org/abs/2207.02506' type: paper - key: 5gsniffer-repo - title: '5GSniffer — open-source 5G NR PDCCH blind decoder (source)' + title: '5GSniffer: open-source 5G NR PDCCH blind decoder (source)' authors: Sprite Lab (Northeastern University) venue: GitHub year: 2023 url: 'https://github.com/spritelab/5GSniffer' type: tool - key: sni5gect-repo - title: 'Sni5Gect — 5G NR sniffing and (downlink) injection framework (source)' + title: 'Sni5Gect: 5G NR sniffing and (downlink) injection framework (source)' authors: ASSET Research Group (SUTD) venue: GitHub year: 2024 @@ -135,25 +135,25 @@ lastResearched: 2026-06-14 ## Mechanism -5G NR carries everything on a CP-OFDM resource grid with flexible numerology (subcarrier spacing 15·2^μ kHz, a FR1 carrier up to 100 MHz wide; this control inherits those signal facts from the NR5G Wayfinder). Cell search starts at the **SS/PBCH block (SSB)**: PSS gives N_ID(2) (0–2), SSS gives N_ID(1) (0–335), and the Physical Cell ID is `PCI = 3·N_ID(1) + N_ID(2)` → 1008 IDs (0–1007). The **MIB**, carried on PBCH inside the SSB, gives the SFN, the SSB position and the SIB1 scheduling; **SIB1**, carried on PDSCH, gives the PLMN (MCC+MNC, i.e. the operator), the cell identity, the Tracking Area Code (TAC) and access information. As in LTE, these broadcast messages are sent in the clear — no confidentiality, integrity or source authentication — so a passive receiver that has recovered the grid reads the cell's full identity and configuration without ever transmitting. +5G NR carries everything on a CP-OFDM resource grid with flexible numerology (subcarrier spacing 15·2^μ kHz, a FR1 carrier up to 100 MHz wide; this control inherits those signal facts from the NR5G Wayfinder). Cell search starts at the **SS/PBCH block (SSB)**: PSS gives N_ID(2) (0 to 2), SSS gives N_ID(1) (0 to 335), and the Physical Cell ID is `PCI = 3·N_ID(1) + N_ID(2)` → 1008 IDs (0 to 1007). The **MIB**, carried on PBCH inside the SSB, gives the SFN, the SSB position and the SIB1 scheduling; **SIB1**, carried on PDSCH, gives the PLMN (MCC+MNC, i.e. the operator), the cell identity, the Tracking Area Code (TAC) and access information. As in LTE, these broadcast messages are sent in the clear, no confidentiality, integrity or source authentication, so a passive receiver that has recovered the grid reads the cell's full identity and configuration without ever transmitting. -The headline 5G improvement is at the subscriber-identity exposure, and it is the core of this control. In LTE the permanent identity (IMSI) could be harvested in the clear off the air; 5G conceals the long-term identity (SUPI) as a **SUCI** before it leaves the device, using ECIES public-key encryption against the home operator's public key, so only the operator's core can recover the permanent identity [nist2026suci]. 3GPP standardises three protection schemes: **Profile A** (Curve25519) and **Profile B** (secp256r1), both with AES-128-CTR and HMAC-SHA-256, and a **null-scheme** that performs no encryption at all [nist2026suci]. The null-scheme is used when the home network is configured to use it or has not provisioned the public key the UE needs to compute a SUCI — in which case the SUPI (the IMSI's MSIN) is transmitted effectively in the clear, reinstating the LTE-style permanent-identity leak. NIST's guidance is explicit that operators should enable SUCI and configure it with a non-null encryption scheme [nist2026suci]; verifying which scheme is actually in use on the air is exactly what this control checks. +The headline 5G improvement is at the subscriber-identity exposure, and it is the core of this control. In LTE the permanent identity (IMSI) could be harvested in the clear off the air; 5G conceals the long-term identity (SUPI) as a **SUCI** before it leaves the device, using ECIES public-key encryption against the home operator's public key, so only the operator's core can recover the permanent identity [nist2026suci]. 3GPP standardises three protection schemes: **Profile A** (Curve25519) and **Profile B** (secp256r1), both with AES-128-CTR and HMAC-SHA-256, and a **null-scheme** that performs no encryption at all [nist2026suci]. The null-scheme is used when the home network is configured to use it or has not provisioned the public key the UE needs to compute a SUCI, in which case the SUPI (the IMSI's MSIN) is transmitted effectively in the clear, reinstating the LTE-style permanent-identity leak. NIST's guidance is explicit that operators should enable SUCI and configure it with a non-null encryption scheme [nist2026suci]; verifying which scheme is actually in use on the air is exactly what this control checks. -Concealment is necessary but not sufficient. Chlosta et al. show a practical **5G SUCI-catcher** in a standalone network: beyond the null-scheme case, even properly ECIES-concealed SUCIs can be **linked across sessions** by abusing the Authentication and Key Agreement (AKA) procedure, so an attacker can still confirm and track a target between encounters without ever recovering the cleartext SUPI [chlosta2021suci]. Separately, the broadcast and pre-authentication messages this control reads are **unauthenticated by design** — there is no source authentication on the MIB/SIB or on pre-auth RRC/NAS — which is the property that underpins the documented 5G fake-cell and protocol-flaw surface (5GReasoner's model-checking found new NAS/RRC design weaknesses including identity and tracking exposure [hussain2019reasoner], and the PWS work shows unauthenticated 5G warning broadcasts can be spoofed or suppressed [bitsikas2022pws]). Those active attacks belong to the Attack layer and require transmitting; here we only read the broadcast to inventory the exposure they build on. +Concealment is necessary but not sufficient. Chlosta et al. show a practical **5G SUCI-catcher** in a standalone network: beyond the null-scheme case, even properly ECIES-concealed SUCIs can be **linked across sessions** by abusing the Authentication and Key Agreement (AKA) procedure, so an attacker can still confirm and track a target between encounters without ever recovering the cleartext SUPI [chlosta2021suci]. Separately, the broadcast and pre-authentication messages this control reads are **unauthenticated by design**, there is no source authentication on the MIB/SIB or on pre-auth RRC/NAS, which is the property that underpins the documented 5G fake-cell and protocol-flaw surface (5GReasoner's model-checking found new NAS/RRC design weaknesses including identity and tracking exposure [hussain2019reasoner], and the PWS work shows unauthenticated 5G warning broadcasts can be spoofed or suppressed [bitsikas2022pws]). Those active attacks belong to the Attack layer and require transmitting; here we only read the broadcast to inventory the exposure they build on. -The passive view is bounded the same way LTE's is. 5G-AKA derives the air-interface ciphering and integrity keys (NEA/NIA: SNOW 3G / AES / ZUC) from the secret on the USIM, shared only with the operator's core, so a passive capture yields no session key and no user-plane content — there is no weak-pairing shortcut. What passive decode yields is **configuration and identity-form exposure**: the cell's PLMN/identity/TAC, the PCI, and crucially *which* identity protection scheme the SUCI uses. Note also that passive 5G NR air-sniffing is markedly less mature than LTE — there is no drop-in passive SA receiver equivalent to srsUE's LTE cell search — so the practical routes (below) are a research PDCCH/MAC sniffer on a real cell, a controlled cell you stand up yourself, or the modem DIAG capture. +The passive view is bounded the same way LTE's is. 5G-AKA derives the air-interface ciphering and integrity keys (NEA/NIA: SNOW 3G / AES / ZUC) from the secret on the USIM, shared only with the operator's core, so a passive capture yields no session key and no user-plane content, there is no weak-pairing shortcut. What passive decode yields is **configuration and identity-form exposure**: the cell's PLMN/identity/TAC, the PCI, and crucially *which* identity protection scheme the SUCI uses. Note also that passive 5G NR air-sniffing is markedly less mature than LTE, there is no drop-in passive SA receiver equivalent to srsUE's LTE cell search, so the practical routes (below) are a research PDCCH/MAC sniffer on a real cell, a controlled cell you stand up yourself, or the modem DIAG capture. ## Procedure -> Authorised testing only. The passive read steps below do not transmit, but you are receiving on licensed cellular spectrum — do so in line with local law and your engagement scope. Any step that stands up a cell (Step 2, alternative B) transmits in licensed spectrum and must be done on your own equipment, with a test SIM, inside RF shielding, under an authorised test licence — never radiate on a live operator's band. +> Authorised testing only. The passive read steps below do not transmit, but you are receiving on licensed cellular spectrum, do so in line with local law and your engagement scope. Any step that stands up a cell (Step 2, alternative B) transmits in licensed spectrum and must be done on your own equipment, with a test SIM, inside RF shielding, under an authorised test licence, never radiate on a live operator's band. 1. **Confirm the target carrier first.** You must already know the band/NR-ARFCN and bandwidth (see RFSAM-RES-22 for the cellular identify-and-capture flow, and RFSAM-RES-09 for the disciplined-clock capture that OFDM grid recovery requires). Sanity-check on a waterfall that you are looking at a 5G downlink carrier and its SSB: ```bash gqrx ``` - Expected: a flat-topped CP-OFDM carrier (up to 100 MHz wide in FR1, so a single HackRF/B210 view shows only a slice — enough to locate the SSB) centred on the NR-ARFCN frequency. Note the centre frequency and the SSB. + Expected: a flat-topped CP-OFDM carrier (up to 100 MHz wide in FR1, so a single HackRF/B210 view shows only a slice, enough to locate the SSB) centred on the NR-ARFCN frequency. Note the centre frequency and the SSB. -2. **Recover the cell and read its broadcast identity.** Two routes — pick one: +2. **Recover the cell and read its broadcast identity.** Two routes, pick one: **(A) No-SDR modem route (fastest, fully passive).** Pull the serving cell's signalling off a Qualcomm modem's DIAG interface into Wireshark: ```bash @@ -161,31 +161,31 @@ The passive view is bounded the same way LTE's is. 5G-AKA derives the air-interf ``` Expected: a live GSMTAP PCAP in Wireshark; the modem reports the serving cell (band, NR-ARFCN, PLMN, cell identity) and the registration signalling. (5G frame support is modem/firmware-dependent.) - **(B) Controlled-cell route, for studying cell search where no turnkey passive SA receiver exists.** Stand up your own SA gNB on an SDR with srsRAN Project behind a 5G core (Open5GS/free5GC) and a test UE, then read the SSB/MIB/SIB1 and NGAP end-to-end. (Radiates — authorised, RF-contained use only; the srsRAN_Project repo is archived, so take current builds from srsran.com.) + **(B) Controlled-cell route, for studying cell search where no turnkey passive SA receiver exists.** Stand up your own SA gNB on an SDR with srsRAN Project behind a 5G core (Open5GS/free5GC) and a test UE, then read the SSB/MIB/SIB1 and NGAP end-to-end. (Radiates, authorised, RF-contained use only; the srsRAN_Project repo is archived, so take current builds from srsran.com.) -3. **Read the clear-text cell configuration** in Wireshark from whichever capture Step 2 produced. Filter `nr-rrc.SIB1` (and `nr-rrc.BCCH_BCH_Message` for the MIB). Expected: SIB1 shows the **PLMN (MCC+MNC = operator)**, the **cell identity** and the **TAC** — all in the clear, no decryption performed. Record them as the cell-configuration exposure. +3. **Read the clear-text cell configuration** in Wireshark from whichever capture Step 2 produced. Filter `nr-rrc.SIB1` (and `nr-rrc.BCCH_BCH_Message` for the MIB). Expected: SIB1 shows the **PLMN (MCC+MNC = operator)**, the **cell identity** and the **TAC**, all in the clear, no decryption performed. Record them as the cell-configuration exposure. 4. **Observe the registration exchange and inventory the subscriber-identity form.** In the same capture, filter the NAS-5GS registration request (`nas-5gs.mm.type_id` / the Registration Request message) and inspect the **mobile identity IE**. Expected: a **SUCI** (the 5G-GUTI is used on re-registration; a fresh registration carries the SUCI). Read the SUCI's **Protection Scheme Identifier**: - `0` = **null-scheme** → the MSIN (the SUPI/IMSI body) is in the clear: a reportable permanent-identity exposure [nist2026suci][chlosta2021suci]. - `1`/`2` = **Profile A / Profile B** → ECIES-concealed; the permanent identity is not recoverable from the capture, but record that SUCIs are still **linkable via the AKA procedure** [chlosta2021suci]. This protection-scheme value is the headline finding of the control. -5. **(Optional) Passive control-channel view** with 5GSniffer to enumerate active RNTIs/DCIs from the PDCCH (a scheduling/activity inventory, FR1 FDD, research-grade — the current release recommends working from a recorded I/Q file): +5. **(Optional) Passive control-channel view** with 5GSniffer to enumerate active RNTIs/DCIs from the PDCCH (a scheduling/activity inventory, FR1 FDD, research-grade, the current release recommends working from a recorded I/Q file): ```bash ./5g_sniffer config.toml ``` Expected: a running list of decoded DCIs and the RNTIs active in the cell [5gsniffer-repo]. Sni5Gect gives an over-the-air MAC-NR view in Wireshark if you have the heavier USRP/host setup [sni5gect-repo]. -6. **Inventory the result.** Record, as the control's finding, exactly what was recoverable purely passively: the cell PLMN/identity/TAC and PCI (broadcast, in the clear); and — the decisive item — whether the subscriber identity was concealed as a SUCI under Profile A/B (permanent identity protected, but linkable) or fell back to the **null-scheme** (permanent identity effectively in the clear). A null-scheme deployment is the headline exposure; a Profile A/B deployment downgrades the finding to configuration/metadata exposure plus AKA-linkability. +6. **Inventory the result.** Record, as the control's finding, exactly what was recoverable purely passively: the cell PLMN/identity/TAC and PCI (broadcast, in the clear); and, the decisive item, whether the subscriber identity was concealed as a SUCI under Profile A/B (permanent identity protected, but linkable) or fell back to the **null-scheme** (permanent identity effectively in the clear). A null-scheme deployment is the headline exposure; a Profile A/B deployment downgrades the finding to configuration/metadata exposure plus AKA-linkability. ## Field case -Illustrative walkthrough — substitute the values you capture. This is a representative, reproducible procedure against an **authorised test cell** (your own srsRAN Project + Open5GS SA lab on a test NR-ARFCN inside RF shielding, or your own live subscription captured with operator permission via the QCSuper modem route), not a record of a measured engagement. No specific measured field finding is asserted below; every measured value is a `[FILL: …]` placeholder you replace with what you actually read off your own authorised capture. +Illustrative walkthrough, substitute the values you capture. This is a representative, reproducible procedure against an **authorised test cell** (your own srsRAN Project + Open5GS SA lab on a test NR-ARFCN inside RF shielding, or your own live subscription captured with operator permission via the QCSuper modem route), not a record of a measured engagement. No specific measured field finding is asserted below; every measured value is a `[FILL: …]` placeholder you replace with what you actually read off your own authorised capture. -- Step 1–2 located the n78 carrier and SSB and produced a Wireshark capture; the cell reported `PCI=[FILL: measured PCI]`. -- Step 3 read SIB1 in the clear: PLMN `[FILL: measured MCC-MNC]`, cell identity `[FILL: measured NCI]`, TAC `[FILL: measured TAC]` — no decryption performed. +- Step 1 to 2 located the n78 carrier and SSB and produced a Wireshark capture; the cell reported `PCI=[FILL: measured PCI]`. +- Step 3 read SIB1 in the clear: PLMN `[FILL: measured MCC-MNC]`, cell identity `[FILL: measured NCI]`, TAC `[FILL: measured TAC]`, no decryption performed. - Step 4 inspected the NAS-5GS Registration Request mobile-identity IE and read the SUCI Protection Scheme Identifier as `[FILL: measured scheme id 0/1/2]`. In this lab the core was configured for `[FILL: null-scheme or Profile A/B]`: - - If `[FILL: …]` = null-scheme, the MSIN `[FILL: measured/omit]` was visible in the clear — an LTE-style permanent-identity exposure that this control exists to catch [nist2026suci][chlosta2021suci]. + - If `[FILL: …]` = null-scheme, the MSIN `[FILL: measured/omit]` was visible in the clear, an LTE-style permanent-identity exposure that this control exists to catch [nist2026suci][chlosta2021suci]. - If `[FILL: …]` = Profile A/B, the permanent identity was not recoverable; the reportable exposure is the in-the-clear cell configuration plus the documented AKA-based SUCI linkability [chlosta2021suci]. ## Remediation @@ -193,5 +193,5 @@ Illustrative walkthrough — substitute the values you capture. This is a repres This is largely a standards/operator concern: in-the-clear broadcast configuration is inherent to the 5G air interface, so for most assessments the control *documents the exposure*; the one device/operator-actionable item is the SUCI protection scheme. Layered guidance: - **Developer (UE / modem / SIM personalisation):** Ensure the USIM is provisioned with the home-network public key and a non-null protection scheme so the UE actually computes an ECIES-concealed SUCI; do not leak additional stable identifiers above the link that re-enable tracking once the 5G-GUTI rotates. -- **Integrator (network / operator):** Enable SUCI and configure it with a **non-null** encryption cipher scheme (Profile A or B) — the explicit NIST recommendation [nist2026suci]; provision the home-network public key on subscriber SIMs; rotate the 5G-GUTI frequently to break the continuity a passive observer needs for tracking; minimise sensitive configuration broadcast in SIBs. -- **Operator / programme (defence-in-depth):** Treat the in-the-clear, unauthenticated broadcast as observable and plan accordingly — note that even with a non-null SUCI, captured identifiers remain linkable via the AKA procedure [chlosta2021suci], and that the unauthenticated broadcast/pre-auth surface is what underpins the documented fake-cell and PWS attacks [hussain2019reasoner][bitsikas2022pws]; deploy false-base-station / cell-site-simulator monitoring where the threat model warrants it. +- **Integrator (network / operator):** Enable SUCI and configure it with a **non-null** encryption cipher scheme (Profile A or B), the explicit NIST recommendation [nist2026suci]; provision the home-network public key on subscriber SIMs; rotate the 5G-GUTI frequently to break the continuity a passive observer needs for tracking; minimise sensitive configuration broadcast in SIBs. +- **Operator / programme (defence-in-depth):** Treat the in-the-clear, unauthenticated broadcast as observable and plan accordingly, note that even with a non-null SUCI, captured identifiers remain linkable via the AKA procedure [chlosta2021suci], and that the unauthenticated broadcast/pre-auth surface is what underpins the documented fake-cell and PWS attacks [hussain2019reasoner][bitsikas2022pws]; deploy false-base-station / cell-site-simulator monitoring where the threat model warrants it. diff --git a/src/content/controls/rfsam-nr5g-sp-01.md b/src/content/controls/rfsam-nr5g-sp-01.md index 8fb48d2..dd34969 100644 --- a/src/content/controls/rfsam-nr5g-sp-01.md +++ b/src/content/controls/rfsam-nr5g-sp-01.md @@ -13,10 +13,10 @@ objective: >- Establish which operator (PLMN), band, NR-ARFCN and Physical Cell ID (PCI) a target 5G NR cell presents, confirm whether it is Standalone or Non-Standalone, and verify the cell falls inside the receiver's tuning and instantaneous-bandwidth - envelope — the spectrum-layer prerequisite that scopes every later 5G NR control. + envelope, the spectrum-layer prerequisite that scopes every later 5G NR control. intro: >- 5G NR FR1 lives in licensed slices scattered from roughly 700 MHz to 3.8 GHz, - and a single carrier can be up to 100 MHz wide — wider than any LTE channel and + and a single carrier can be up to 100 MHz wide, wider than any LTE channel and wider than a single HackRF or B210 view. Before any capture is meaningful you must find the downlink carrier, read its centre frequency (NR-ARFCN) and width on a waterfall, then read the cell identity (PCI, PLMN, TAC) that 5G broadcasts in @@ -25,15 +25,15 @@ intro: >- is passive, but anything that transmits is for authorised testing only. prerequisites: hardware: - - 'A receive SDR that covers the target FR1 band: HackRF One (1 MHz–6 GHz, ~20 MHz IBW), or a USRP B210 / bladeRF 2.0 micro / SignalSDR Pro for wider carriers and a steadier (GPSDO-disciplined) reference' + - 'A receive SDR that covers the target FR1 band: HackRF One (1 MHz to 6 GHz, ~20 MHz IBW), or a USRP B210 / bladeRF 2.0 micro / SignalSDR Pro for wider carriers and a steadier (GPSDO-disciplined) reference' - 'Optionally a Qualcomm-based 5G modem (Quectel RM500Q) or rooted Qualcomm phone exposing the DIAG port, with a registered/test SIM, for a no-SDR serving-cell read' software: - 'gqrx for the live spectrum / waterfall view (sub-6 GHz only)' - 'QCSuper for the modem DIAG → GSMTAP → Wireshark serving-cell read' signal: freq: >- - Licensed cellular FR1 ~410 MHz–7.125 GHz (common bands n28/700, n1/2100, - n3/1800, n78/3.3–3.8 GHz TDD); FR2 mmWave ~24.25–52.6 GHz is out of reach of + Licensed cellular FR1 ~410 MHz to 7.125 GHz (common bands n28/700, n1/2100, + n3/1800, n78/3.3 to 3.8 GHz TDD); FR2 mmWave ~24.25 to 52.6 GHz is out of reach of common SDRs. Carrier identified by its NR-ARFCN bandwidth: >- Flexible numerology, subcarrier spacing 15·2^μ kHz (15/30/60/120 kHz); a @@ -46,8 +46,8 @@ attacks: - borgaonkar2019aka - hussain2019reasoner impact: >- - The same passive, in-the-clear cell information this control inventories — - PCI, NR-ARFCN, PLMN, TAC and the SIB configuration — is the reconnaissance an + The same passive, in-the-clear cell information this control inventories, + PCI, NR-ARFCN, PLMN, TAC and the SIB configuration, is the reconnaissance an attacker performs to stand up a rogue gNB that mimics a legitimate cell and lure a target UE into the pre-authentication NAS/RRC exchange, where AKA activity-monitoring and other pre-auth weaknesses live. @@ -62,17 +62,17 @@ attacks: side-channel and pre-auth RRC/NAS surface remain documented threats. references: - key: ts38211 - title: '3GPP TS 38.211 — NR; Physical channels and modulation (PSS/SSS, SSB, PCI, CP-OFDM, numerology)' + title: '3GPP TS 38.211: NR; Physical channels and modulation (PSS/SSS, SSB, PCI, CP-OFDM, numerology)' venue: 3GPP url: 'https://portal.3gpp.org/desktopmodules/Specifications/SpecificationDetails.aspx?specificationId=3213' type: standard - key: ts38101 - title: '3GPP TS 38.101-1 — NR; UE radio transmission and reception; Part 1: Range 1 Standalone (operating bands, NR-ARFCN, channel bandwidths)' + title: '3GPP TS 38.101-1: NR; UE radio transmission and reception; Part 1: Range 1 Standalone (operating bands, NR-ARFCN, channel bandwidths)' venue: 3GPP url: 'https://portal.3gpp.org/desktopmodules/Specifications/SpecificationDetails.aspx?specificationId=3283' type: standard - key: ts38331 - title: '3GPP TS 38.331 — NR; Radio Resource Control (RRC); Protocol specification (MIB, SIB1: PLMN, cell identity, TAC)' + title: '3GPP TS 38.331: NR; Radio Resource Control (RRC); Protocol specification (MIB, SIB1: PLMN, cell identity, TAC)' venue: 3GPP url: 'https://portal.3gpp.org/desktopmodules/Specifications/SpecificationDetails.aspx?specificationId=3197' type: standard @@ -91,19 +91,19 @@ references: url: 'https://dl.acm.org/doi/10.1145/3319535.3354263' type: paper - key: gqrx - title: 'gqrx — software-defined radio receiver (GNU Radio + Qt) for spectrum/waterfall view' + title: 'gqrx: software-defined radio receiver (GNU Radio + Qt) for spectrum/waterfall view' authors: A. Csete (OZ9AEC) et al. venue: GitHub url: 'https://github.com/gqrx-sdr/gqrx' type: tool - key: qcsuper - title: 'QCSuper — capture raw 2G/3G/4G/5G radio frames from Qualcomm modems via the DIAG port (GSMTAP → Wireshark)' + title: 'QCSuper: capture raw 2G/3G/4G/5G radio frames from Qualcomm modems via the DIAG port (GSMTAP → Wireshark)' authors: P1 Security venue: GitHub url: 'https://github.com/P1sec/QCSuper' type: tool - key: spritelab5gsniffer - title: '5GSniffer — open-source 5G NR control-channel sniffer, with a sample recording of a real n71 operator cell (README "An example", SpriteLab-Private5G.toml, sample_output.out)' + title: '5GSniffer: open-source 5G NR control-channel sniffer, with a sample recording of a real n71 operator cell (README "An example", SpriteLab-Private5G.toml, sample_output.out)' authors: 'N. Ludant, P. Robyns, G. Noubir et al. (Northeastern SpriteLab); IEEE S&P 2023' venue: GitHub url: 'https://github.com/spritelab/5GSniffer' @@ -127,50 +127,50 @@ lastResearched: 2026-06-14 --- ## Mechanism -A 5G NR deployment is a grid of cells. Each cell transmits a downlink carrier identified by its NR-ARFCN, and the NR-ARFCN-to-frequency mapping and the set of FR1 operating bands are defined in 3GPP TS 38.101-1 [ts38101]. Unlike LTE's fixed channel grid, NR uses flexible numerology — subcarrier spacing 15·2^μ kHz (15/30/60/120 kHz) — and a single FR1 carrier can be up to 100 MHz wide [ts38211][ts38101]. Because the downlink is CP-OFDM, on a waterfall a live carrier appears as a steady, flat "wall" of energy whose width indicates the channel bandwidth [ts38211]. Which SDR can even tune it is a hard constraint: common SDR tuners stop near 6 GHz, so FR1 (410 MHz–7.125 GHz) is reachable but FR2 mmWave (24.25–52.6 GHz) is not — confirming an FR2 cell needs a mmWave front-end or a commercial scanner, not the SDRs in this kit. These FR1/FR2 spans are the 3GPP TS 38.101-1 / TS 38.101-2 range definitions; the common-band designations used here (n28/700, n1/2100, n3/1800, n78/3.3–3.8 GHz TDD) match the published operating-band tables, though precise per-band channel edges vary by region and operator licence and should be reconciled against the current TS 38.101-1 band table for a given market [ts38101]. +A 5G NR deployment is a grid of cells. Each cell transmits a downlink carrier identified by its NR-ARFCN, and the NR-ARFCN-to-frequency mapping and the set of FR1 operating bands are defined in 3GPP TS 38.101-1 [ts38101]. Unlike LTE's fixed channel grid, NR uses flexible numerology, subcarrier spacing 15·2^μ kHz (15/30/60/120 kHz), and a single FR1 carrier can be up to 100 MHz wide [ts38211][ts38101]. Because the downlink is CP-OFDM, on a waterfall a live carrier appears as a steady, flat "wall" of energy whose width indicates the channel bandwidth [ts38211]. Which SDR can even tune it is a hard constraint: common SDR tuners stop near 6 GHz, so FR1 (410 MHz to 7.125 GHz) is reachable but FR2 mmWave (24.25 to 52.6 GHz) is not, confirming an FR2 cell needs a mmWave front-end or a commercial scanner, not the SDRs in this kit. These FR1/FR2 spans are the 3GPP TS 38.101-1 / TS 38.101-2 range definitions; the common-band designations used here (n28/700, n1/2100, n3/1800, n78/3.3 to 3.8 GHz TDD) match the published operating-band tables, though precise per-band channel edges vary by region and operator licence and should be reconciled against the current TS 38.101-1 band table for a given market [ts38101]. -Once the carrier is found, the cell identifies itself in the clear. Cell search synchronises on the SS/PBCH block (SSB): the Primary Synchronisation Signal (PSS) gives N_ID(2) (0–2) and the Secondary Synchronisation Signal (SSS) gives N_ID(1) (0–335), so the Physical Cell ID PCI = 3·N_ID(1) + N_ID(2), yielding 1008 PCIs (0–1007) — twice LTE's 504 [ts38211]. The Master Information Block (MIB) on the PBCH inside the SSB carries the SFN, the SSB position and the SIB1 scheduling; System Information Block 1 (SIB1), carried on the PDSCH, carries the operator identity (PLMN = MCC+MNC), the cell identity, the Tracking Area Code (TAC) and access information [ts38331]. None of this is encrypted — synchronisation, MIB and SIB1 are broadcast unprotected by design, exactly as in LTE, so any receiver in range reads the cell's identity without a credential [ts38211][ts38331]. +Once the carrier is found, the cell identifies itself in the clear. Cell search synchronises on the SS/PBCH block (SSB): the Primary Synchronisation Signal (PSS) gives N_ID(2) (0 to 2) and the Secondary Synchronisation Signal (SSS) gives N_ID(1) (0 to 335), so the Physical Cell ID PCI = 3·N_ID(1) + N_ID(2), yielding 1008 PCIs (0 to 1007), twice LTE's 504 [ts38211]. The Master Information Block (MIB) on the PBCH inside the SSB carries the SFN, the SSB position and the SIB1 scheduling; System Information Block 1 (SIB1), carried on the PDSCH, carries the operator identity (PLMN = MCC+MNC), the cell identity, the Tracking Area Code (TAC) and access information [ts38331]. None of this is encrypted, synchronisation, MIB and SIB1 are broadcast unprotected by design, exactly as in LTE, so any receiver in range reads the cell's identity without a credential [ts38211][ts38331]. -Whether there is a 5G core to talk to at all is part of this baseline: a Standalone (SA) cell pairs 5G NR with a 5G core (AMF/SMF/UPF), while a Non-Standalone (NSA) cell is a 5G NR carrier anchored to an LTE eNB + EPC, so the control plane still rides LTE. That same unprotected broadcast and pre-authentication information is what an attacker exploits: a rogue gNB begins by reading this PCI/NR-ARFCN/PLMN/SIB configuration so it can mimic a legitimate cell and lure a target UE into the pre-authentication NAS/RRC exchange, where 5GReasoner documents control-plane weaknesses [hussain2019reasoner]. 5G is a genuine improvement over LTE here — the long-term identity (SUPI/IMSI) is concealed as a SUCI using the home network's public key (ECIES), closing the LTE-style cleartext-IMSI harvest off the air — but the concealment is not total: Borgaonkar et al. show a sequence-number side-channel in the AKA protocol (3G/4G/5G) that still enables subscriber-activity monitoring [borgaonkar2019aka]. Performing this inventory passively is therefore both the auditor's scoping step and a mirror of the attacker's reconnaissance phase. This control owns the spectrum-layer half — find the carrier and read the cell identity; the deeper, research-grade passive control-channel decode is the work of the later 5G NR capture controls. +Whether there is a 5G core to talk to at all is part of this baseline: a Standalone (SA) cell pairs 5G NR with a 5G core (AMF/SMF/UPF), while a Non-Standalone (NSA) cell is a 5G NR carrier anchored to an LTE eNB + EPC, so the control plane still rides LTE. That same unprotected broadcast and pre-authentication information is what an attacker exploits: a rogue gNB begins by reading this PCI/NR-ARFCN/PLMN/SIB configuration so it can mimic a legitimate cell and lure a target UE into the pre-authentication NAS/RRC exchange, where 5GReasoner documents control-plane weaknesses [hussain2019reasoner]. 5G is a genuine improvement over LTE here, the long-term identity (SUPI/IMSI) is concealed as a SUCI using the home network's public key (ECIES), closing the LTE-style cleartext-IMSI harvest off the air, but the concealment is not total: Borgaonkar et al. show a sequence-number side-channel in the AKA protocol (3G/4G/5G) that still enables subscriber-activity monitoring [borgaonkar2019aka]. Performing this inventory passively is therefore both the auditor's scoping step and a mirror of the attacker's reconnaissance phase. This control owns the spectrum-layer half, find the carrier and read the cell identity; the deeper, research-grade passive control-channel decode is the work of the later 5G NR capture controls. ## Procedure -> Authorised testing only. Every step below is receive-only — you read what the +> Authorised testing only. Every step below is receive-only, you read what the > network already broadcasts. Do not transmit on licensed cellular spectrum. -1. **Scope the candidate bands and confirm your radio reaches them.** Decide which bands are plausible for the operators in your region (for example n28/700 MHz, n3/1800 MHz, n1/2100 MHz, n78/3.3–3.8 GHz TDD). Confirm your SDR tunes them: a HackRF/B210/bladeRF/SignalSDR reaches FR1, but none reach FR2 mmWave (~24–52 GHz) [ts38101]. A 100 MHz n78 carrier exceeds a single HackRF view (~20 MHz) and a B210 view (~56 MHz) — you will see a slice, enough to locate the SSB, not the whole carrier. +1. **Scope the candidate bands and confirm your radio reaches them.** Decide which bands are plausible for the operators in your region (for example n28/700 MHz, n3/1800 MHz, n1/2100 MHz, n78/3.3 to 3.8 GHz TDD). Confirm your SDR tunes them: a HackRF/B210/bladeRF/SignalSDR reaches FR1, but none reach FR2 mmWave (~24 to 52 GHz) [ts38101]. A 100 MHz n78 carrier exceeds a single HackRF view (~20 MHz) and a B210 view (~56 MHz), you will see a slice, enough to locate the SSB, not the whole carrier. 2. **Find the downlink carrier on a waterfall** with gqrx. Tune across the candidate band and look for the steady CP-OFDM "wall": ```bash gqrx ``` - In the GUI, set the device to your SDR, tune to a candidate downlink centre and watch the waterfall. A live 5G NR downlink shows as a flat, continuous block; read its centre frequency and estimate its width (e.g. a ~100 MHz n78 carrier will overflow a single narrow view). Record the centre frequency — this is the carrier you will map to an NR-ARFCN [ts38211][gqrx]. Note that gqrx is sub-6 GHz only; FR2 cannot be confirmed this way. + In the GUI, set the device to your SDR, tune to a candidate downlink centre and watch the waterfall. A live 5G NR downlink shows as a flat, continuous block; read its centre frequency and estimate its width (e.g. a ~100 MHz n78 carrier will overflow a single narrow view). Record the centre frequency, this is the carrier you will map to an NR-ARFCN [ts38211][gqrx]. Note that gqrx is sub-6 GHz only; FR2 cannot be confirmed this way. -3. **(No-SDR cross-check) Read the serving cell from a Qualcomm 5G modem** over its DIAG interface with QCSuper, the fastest way to confirm which cell a target UE is camped on and read its identity before committing capture hardware. QCSuper pulls the raw radio frames the modem already receives, wraps them in GSMTAP and streams a live PCAP into Wireshark — passive, it reads what the modem receives: +3. **(No-SDR cross-check) Read the serving cell from a Qualcomm 5G modem** over its DIAG interface with QCSuper, the fastest way to confirm which cell a target UE is camped on and read its identity before committing capture hardware. QCSuper pulls the raw radio frames the modem already receives, wraps them in GSMTAP and streams a live PCAP into Wireshark, passive, it reads what the modem receives: ```bash QCSuper.py --usb-modem /dev/ttyUSB0 --wireshark-live ``` - In Wireshark, filter on the 5G NR RRC frames and read the broadcast: the SIB1 carries the PLMN (MCC-MNC), cell identity and TAC, and the SSB/MIB carries the PCI and SFN — confirming operator, band and cell identity from a route that needs no SDR cell-search to get right [qcsuper][ts38331]. 5G frame support is modem/firmware-dependent (e.g. a Quectel RM500Q), so verify your modem reports NR before relying on this route. + In Wireshark, filter on the 5G NR RRC frames and read the broadcast: the SIB1 carries the PLMN (MCC-MNC), cell identity and TAC, and the SSB/MIB carries the PCI and SFN, confirming operator, band and cell identity from a route that needs no SDR cell-search to get right [qcsuper][ts38331]. 5G frame support is modem/firmware-dependent (e.g. a Quectel RM500Q), so verify your modem reports NR before relying on this route. 4. **Determine SA vs NSA.** From the modem read (or from the SIB content), establish whether the cell is Standalone (its own 5G core; NR RRC/NAS-5GS) or Non-Standalone (5G NR carrier anchored to an LTE eNB, control plane on LTE). This decides whether there is a 5G core to interact with in later controls. -5. **Record the inventory.** For each cell, capture: operator (PLMN MCC-MNC), band, downlink NR-ARFCN, PCI, numerology/bandwidth, TAC and SA/NSA mode. Mark which cells fall inside your SDR's tuning and instantaneous-bandwidth envelope — those are the sniffable targets that scope the later 5G NR capture controls. For the full identify-then-capture flow on a disciplined reference, see RFSAM-RES-22, RFSAM-RES-09 and RFSAM-RES-01. +5. **Record the inventory.** For each cell, capture: operator (PLMN MCC-MNC), band, downlink NR-ARFCN, PCI, numerology/bandwidth, TAC and SA/NSA mode. Mark which cells fall inside your SDR's tuning and instantaneous-bandwidth envelope, those are the sniffable targets that scope the later 5G NR capture controls. For the full identify-then-capture flow on a disciplined reference, see RFSAM-RES-22, RFSAM-RES-09 and RFSAM-RES-01. ## Field case -Documented public example — substitute the values you capture against your own +Documented public example, substitute the values you capture against your own target. This walk-through is grounded in a recording that ships with a published tool, not in a measured field capture of our own; the numbers below are read from that public dataset and its expected output, not produced live here. -A recording of a real 5G operator cell that ships with 5GSniffer (spritelab/5GSniffer, IEEE S&P 2023) makes the identify-the-carrier step concrete [spritelab5gsniffer]. As the project's README "An example" section describes, the authors recorded a 5G operator in their area operating over a 10 MHz channel in band n71 (the 600 MHz FDD band), at 15 kHz subcarrier spacing (SCS numerology 0). This is exactly the spectrum-layer read this control owns: on a waterfall the carrier appears as a CP-OFDM downlink "wall" whose centre maps to an NR-ARFCN. From the log, the carrier's SSB sits at absoluteFrequencySSB / SSB-ARFCN 125550, which translates to 627.750 MHz (the TS 38.104 mapping 5 kHz × 125550 = 627.750 MHz), with absoluteFrequencyPointA 124464 = 622.320 MHz; the shipped configuration `5gsniffer/SpriteLab-Private5G.toml` records the recording's centre as `frequency = 627750000` (627.750 MHz) [spritelab5gsniffer][ts38211]. Running cell search over that recording, the tool's shipped expected output `5gsniffer/sample_output.out` decodes the cell as PCI / Cell ID 1 [spritelab5gsniffer]. So from this one public capture the operator-facing inventory reads: band n71 (FDD), 10 MHz channel, 15 kHz SCS, downlink SSB at NR-ARFCN 125550 (627.750 MHz), PointA NR-ARFCN 124464 (622.320 MHz), PCI 1 — every spectrum-layer value the procedure asks for, confirmed against a tool's own config and expected decode rather than asserted. (The PLMN MCC-MNC, TAC and SA/NSA mode are operator-deployment details the cross-check routes in steps 3–4 add; the published recording fixes the carrier/NR-ARFCN/PCI half that this spectrum-layer control owns.) FR2 mmWave cells, if any operate in the area, could not be checked from such a sub-6 GHz recording: the SDRs in this kit stop at 6 GHz [ts38101]. +A recording of a real 5G operator cell that ships with 5GSniffer (spritelab/5GSniffer, IEEE S&P 2023) makes the identify-the-carrier step concrete [spritelab5gsniffer]. As the project's README "An example" section describes, the authors recorded a 5G operator in their area operating over a 10 MHz channel in band n71 (the 600 MHz FDD band), at 15 kHz subcarrier spacing (SCS numerology 0). This is exactly the spectrum-layer read this control owns: on a waterfall the carrier appears as a CP-OFDM downlink "wall" whose centre maps to an NR-ARFCN. From the log, the carrier's SSB sits at absoluteFrequencySSB / SSB-ARFCN 125550, which translates to 627.750 MHz (the TS 38.104 mapping 5 kHz × 125550 = 627.750 MHz), with absoluteFrequencyPointA 124464 = 622.320 MHz; the shipped configuration `5gsniffer/SpriteLab-Private5G.toml` records the recording's centre as `frequency = 627750000` (627.750 MHz) [spritelab5gsniffer][ts38211]. Running cell search over that recording, the tool's shipped expected output `5gsniffer/sample_output.out` decodes the cell as PCI / Cell ID 1 [spritelab5gsniffer]. So from this one public capture the operator-facing inventory reads: band n71 (FDD), 10 MHz channel, 15 kHz SCS, downlink SSB at NR-ARFCN 125550 (627.750 MHz), PointA NR-ARFCN 124464 (622.320 MHz), PCI 1, every spectrum-layer value the procedure asks for, confirmed against a tool's own config and expected decode rather than asserted. (The PLMN MCC-MNC, TAC and SA/NSA mode are operator-deployment details the cross-check routes in steps 3 to 4 add; the published recording fixes the carrier/NR-ARFCN/PCI half that this spectrum-layer control owns.) FR2 mmWave cells, if any operate in the area, could not be checked from such a sub-6 GHz recording: the SDRs in this kit stop at 6 GHz [ts38101]. ## Remediation -This is an environmental baseline and target-selection step, not a device defect — the "weakness" it surfaces is inherent to 5G NR's unprotected broadcast design, the same as LTE [ts38211][ts38331]. Layered guidance for what *can* be hardened: +This is an environmental baseline and target-selection step, not a device defect, the "weakness" it surfaces is inherent to 5G NR's unprotected broadcast design, the same as LTE [ts38211][ts38331]. Layered guidance for what *can* be hardened: -- **Network operator** — you cannot encrypt PSS/SSS/SSB/MIB/SIB1, but you can minimise what the *clear* broadcast leaks and exploit 5G's improvements: ensure subscriber identity is sent only as a SUCI and never falls back to a cleartext SUPI/IMSI, deploy the network-side false-base-station detection and broadcast-consistency measures defined for 5G, and monitor for anomalous PCIs/NR-ARFCNs/SIB configurations that indicate a rogue gNB mimicking your network [hussain2019reasoner][borgaonkar2019aka]. +- **Network operator**, you cannot encrypt PSS/SSS/SSB/MIB/SIB1, but you can minimise what the *clear* broadcast leaks and exploit 5G's improvements: ensure subscriber identity is sent only as a SUCI and never falls back to a cleartext SUPI/IMSI, deploy the network-side false-base-station detection and broadcast-consistency measures defined for 5G, and monitor for anomalous PCIs/NR-ARFCNs/SIB configurations that indicate a rogue gNB mimicking your network [hussain2019reasoner][borgaonkar2019aka]. -- **Device integrator** — select 5G basebands/modems that implement fake-base-station and downgrade detection, that resist being lured into a rogue cell's pre-authentication NAS/RRC exchange, and that do not leak device capabilities or activity patterns pre-authentication [hussain2019reasoner][borgaonkar2019aka]; expose modem diagnostics (the DIAG interface) only to authorised tooling, since the same passive read this control performs is also an attacker's reconnaissance feed. +- **Device integrator**, select 5G basebands/modems that implement fake-base-station and downgrade detection, that resist being lured into a rogue cell's pre-authentication NAS/RRC exchange, and that do not leak device capabilities or activity patterns pre-authentication [hussain2019reasoner][borgaonkar2019aka]; expose modem diagnostics (the DIAG interface) only to authorised tooling, since the same passive read this control performs is also an attacker's reconnaissance feed. -- **Auditor / operator of the test** — keep this step strictly receive-only; do not transmit on licensed spectrum. Treat the operator/band/NR-ARFCN/PCI/SA-NSA inventory as scoping data for the assessment, and confirm each target cell is inside your receiver's tuning and bandwidth envelope (and within FR1, not FR2) before committing capture hardware (RFSAM-RES-22, RFSAM-RES-09). +- **Auditor / operator of the test**, keep this step strictly receive-only; do not transmit on licensed spectrum. Treat the operator/band/NR-ARFCN/PCI/SA-NSA inventory as scoping data for the assessment, and confirm each target cell is inside your receiver's tuning and bandwidth envelope (and within FR1, not FR2) before committing capture hardware (RFSAM-RES-22, RFSAM-RES-09). diff --git a/src/content/controls/rfsam-rfid-at-01.md b/src/content/controls/rfsam-rfid-at-01.md index 6276851..368e414 100644 --- a/src/content/controls/rfsam-rfid-at-01.md +++ b/src/content/controls/rfsam-rfid-at-01.md @@ -13,7 +13,7 @@ deferred: false objective: >- Determine whether a recovered RFID/NFC credential can be cloned to a blank or magic card, emulated by a programmable device, or relayed in real time between - a genuine card and a distant reader — establishing whether the reader trusts + a genuine card and a distant reader, establishing whether the reader trusts card data and proximity as proof of authenticity. intro: >- Once identity or sector keys are recovered (RFSAM-RFID-CR-01), the credential @@ -30,7 +30,7 @@ prerequisites: - 'pm3-client (Iceman Proxmark3 firmware/client) for lf/hf search, clone, sim and the hf_reblay standalone relay; ChameleonUltra GUI; BomberCat RelayNFC/MagSpoof firmware' signal: freq: 'LF 125 / 134 kHz · HF 13.56 MHz (near-field, magnetically coupled)' - bandwidth: 'Near-field load modulation — no far-field channel; reads are centimetres by design' + bandwidth: 'Near-field load modulation, no far-field channel; reads are centimetres by design' modulation: 'LF ASK/OOK (EM4100, HID Prox); HF ISO 14443-A/B, ISO 15693 load modulation' skill: intermediate attacks: @@ -41,8 +41,8 @@ attacks: A read-only or Crypto1-recovered credential is written to a blank (T5577) or a UID-writable magic card and presented to the reader as the original. preconditions: >- - The card data is recoverable — an LF ID with no crypto, or an HF card whose - keys were recovered (RFSAM-RFID-CR-01) — and the reader trusts that data + The card data is recoverable, an LF ID with no crypto, or an HF card whose + keys were recovered (RFSAM-RFID-CR-01), and the reader trusts that data (often the UID alone) as identity. summary: >- The baseline failure of non-cryptographic access control: UID-only and @@ -60,7 +60,7 @@ attacks: card-authenticity checks the emulator cannot satisfy. summary: >- Proxmark (hf mf sim / lf … sim), ChameleonUltra or BomberCat present the - credential directly from stored data — for MIFARE Classic the ChameleonUltra + credential directly from stored data, for MIFARE Classic the ChameleonUltra emulates the full Crypto1 exchange. - name: NFC / proximity relay refs: @@ -69,7 +69,7 @@ attacks: - mendoza2020reblay impact: >- The reader transacts with a genuine, remote card it believes is in front of - it — defeating physical proximity without the attacker holding the card's + it, defeating physical proximity without the attacker holding the card's keys. preconditions: >- A live card reachable at the 'mole' end and a target reader at the 'proxy' @@ -92,7 +92,7 @@ attacks: magstripe (the legacy fallback on many payment/access terminals). summary: >- MagSpoof emits a magnetic field that emulates swiping a stripe card to a - standard reader without a physical card — the magstripe analogue of the + standard reader without a physical card, the magstripe analogue of the contactless attacks above. references: - key: francis2010relay @@ -131,7 +131,7 @@ references: url: 'https://electroniccats.com/blog/bombercat-prepare-your-bank-terminal/' type: blog - key: magspoof - title: MagSpoof — wireless magnetic-stripe / credit-card emulation + title: MagSpoof, wireless magnetic-stripe / credit-card emulation authors: Samy Kamkar venue: 'samyk/magspoof (GitHub)' year: 2016 @@ -153,23 +153,23 @@ lastResearched: 2026-06-14 Three escalations follow identity or key recovery, all exploiting the same root cause: the reader trusts card-supplied data, and often mere proximity, as proof of authenticity. -**Cloning** writes recovered data onto a writable blank. An LF EM4100/HID Prox ID — read-only with no crypto — is copied straight to a T5577 ([pm3magic] documents the writable-tag families). An HF MIFARE Classic dump, once its sector keys are recovered (RFSAM-RFID-CR-01), is written to a *magic* card. Magic cards expose block 0, which holds the normally-immutable UID: Gen1a cards accept a Chinese "backdoor" command sequence to rewrite it, while Gen2 cards take a direct write to block 0 — so the clone reproduces the UID and all sector contents [pm3magic]. +**Cloning** writes recovered data onto a writable blank. An LF EM4100/HID Prox ID, read-only with no crypto, is copied straight to a T5577 ([pm3magic] documents the writable-tag families). An HF MIFARE Classic dump, once its sector keys are recovered (RFSAM-RFID-CR-01), is written to a *magic* card. Magic cards expose block 0, which holds the normally-immutable UID: Gen1a cards accept a Chinese "backdoor" command sequence to rewrite it, while Gen2 cards take a direct write to block 0, so the clone reproduces the UID and all sector contents [pm3magic]. -**Emulation** removes the blank entirely: a programmable device presents the credential from stored data. The Proxmark simulates a tag (`hf mf sim` / `lf … sim`), and the ChameleonUltra emulates a full MIFARE Classic including the Crypto1 challenge–response, so a reader that authenticates a sector still accepts the emulator [pm3magic]. +**Emulation** removes the blank entirely: a programmable device presents the credential from stored data. The Proxmark simulates a tag (`hf mf sim` / `lf … sim`), and the ChameleonUltra emulates a full MIFARE Classic including the Crypto1 challenge-response, so a reader that authenticates a sector still accepts the emulator [pm3magic]. -**Relay** is the strongest because it needs neither the card's keys nor the card's presence. Two ends forward the reader↔card exchange in real time: a "mole" near the genuine card and a "proxy" at the target reader, bridged over a low-latency link. The reader believes a card is in its field; in reality the card is arbitrarily far away. Francis, Hancke, Mayes and Markantonakis demonstrated this in practice with two off-the-shelf NFC mobile phones and no custom hardware [francis2010relay], extending Hancke's earlier result that an ISO 14443 proximity card could be relayed over roughly 50 m [hancke2005relay]. The Proxmark implements this as the `hf_reblay` standalone mode, which relays ISO 14443-A over Bluetooth — authored by Salvador Mendoza [mendoza2020reblay]. The BomberCat (PN7150) provides a host/client RelayNFC pairing intended for auditing NFC bank-card acceptance, where the host reads the card and the client emulates it at the terminal [bombercatblog]. Because relay forwards a genuine, fully-authenticated transaction, neither strong card crypto (DESFire AES) nor unknown sector keys stop it — only a reader-side timing bound or distance-bounding protocol does [hancke2005relay]. +**Relay** is the strongest because it needs neither the card's keys nor the card's presence. Two ends forward the reader↔card exchange in real time: a "mole" near the genuine card and a "proxy" at the target reader, bridged over a low-latency link. The reader believes a card is in its field; in reality the card is arbitrarily far away. Francis, Hancke, Mayes and Markantonakis demonstrated this in practice with two off-the-shelf NFC mobile phones and no custom hardware [francis2010relay], extending Hancke's earlier result that an ISO 14443 proximity card could be relayed over roughly 50 m [hancke2005relay]. The Proxmark implements this as the `hf_reblay` standalone mode, which relays ISO 14443-A over Bluetooth, authored by Salvador Mendoza [mendoza2020reblay]. The BomberCat (PN7150) provides a host/client RelayNFC pairing intended for auditing NFC bank-card acceptance, where the host reads the card and the client emulates it at the terminal [bombercatblog]. Because relay forwards a genuine, fully-authenticated transaction, neither strong card crypto (DESFire AES) nor unknown sector keys stop it, only a reader-side timing bound or distance-bounding protocol does [hancke2005relay]. A fourth, parallel path extends impersonation to legacy infrastructure: **MagSpoof** emits a magnetic field emulating a stripe swipe to a standard magstripe reader, without a physical card [magspoof]; BomberCat ships a MagSpoof mode for the magstripe fallback that many payment/access terminals still accept. -This control verifies *which* of clone / emulate / relay (and the magstripe fallback) the target reader is susceptible to — i.e. whether it trusts card data, and proximity, as identity. +This control verifies *which* of clone / emulate / relay (and the magstripe fallback) the target reader is susceptible to, i.e. whether it trusts card data, and proximity, as identity. -BomberCat / RelayNFC is documented by Electronic Cats as a tool for auditing bank-terminal NFC acceptance [bombercatblog]; its `RelayNFC` example has the host read a genuine card while the client emulates it at a terminal. Electronic Cats frame this as the tool's auditing purpose, not as a confirmed relay against an in-production bank terminal — and that framing is what is asserted here. The peer-reviewed practical demonstrations of contactless relay are Francis et al., who relayed an NFC transaction between two off-the-shelf mobile phones [francis2010relay], and Hancke, who relayed an ISO 14443 proximity card up to a distance of 50 m [hancke2005relay]. +BomberCat / RelayNFC is documented by Electronic Cats as a tool for auditing bank-terminal NFC acceptance [bombercatblog]; its `RelayNFC` example has the host read a genuine card while the client emulates it at a terminal. Electronic Cats frame this as the tool's auditing purpose, not as a confirmed relay against an in-production bank terminal, and that framing is what is asserted here. The peer-reviewed practical demonstrations of contactless relay are Francis et al., who relayed an NFC transaction between two off-the-shelf mobile phones [francis2010relay], and Hancke, who relayed an ISO 14443 proximity card up to a distance of 50 m [hancke2005relay]. ## Procedure -> All steps energise, write to, emulate or relay live credentials — do them only against your own cards/readers, with explicit written authorisation, ideally in an RF-shielded test setup. +> All steps energise, write to, emulate or relay live credentials, do them only against your own cards/readers, with explicit written authorisation, ideally in an RF-shielded test setup. -1. **Confirm what the reader actually checks.** Before cloning, establish whether the target reader trusts the UID alone, a full sector read, or an authenticated exchange — this decides whether a UID clone suffices or full key recovery is required. Identify the credential first: +1. **Confirm what the reader actually checks.** Before cloning, establish whether the target reader trusts the UID alone, a full sector read, or an authenticated exchange, this decides whether a UID clone suffices or full key recovery is required. Identify the credential first: ``` pm3 --> lf search pm3 --> hf search @@ -183,7 +183,7 @@ BomberCat / RelayNFC is documented by Electronic Cats as a tool for auditing ban ``` Expected: `Done`/`Cloned`. Re-run `lf search` on the cloned tag to confirm the ID matches, then test against the reader. -3. **Clone an HF MIFARE Classic dump to a magic card.** Using the dump and keys from RFSAM-RFID-CR-01 (`hf mf autopwn` / `hf mf dump` produce `hf-mf--dump.bin`), write the full dump — including block 0/UID — to a magic Gen1a/Gen2 card [pm3magic]: +3. **Clone an HF MIFARE Classic dump to a magic card.** Using the dump and keys from RFSAM-RFID-CR-01 (`hf mf autopwn` / `hf mf dump` produce `hf-mf--dump.bin`), write the full dump, including block 0/UID, to a magic Gen1a/Gen2 card [pm3magic]: ``` pm3 --> hf mf restore --1k --uid 4A6CE843 -k hf-mf-A29558E4-key.bin -f hf-mf-A29558E4-dump.bin ``` @@ -196,7 +196,7 @@ BomberCat / RelayNFC is documented by Electronic Cats as a tool for auditing ban ``` Expected: the Proxmark answers the reader as the card (`#db# Emulating MIFARE…`). Confirm the reader accepts the emulated credential, including a sector authentication for MIFARE Classic. -5. **Relay a live card.** With two Proxmarks (or a BomberCat host/client pair), run the relay so a reader at the proxy end transacts with a card at the mole end [mendoza2020reblay][bombercatblog]. On the Proxmark, the `hf_reblay` standalone mode relays ISO 14443-A over Bluetooth. Expected: the reader completes a transaction with the remote card. **Measure the added latency** and check whether the reader still completes — this is the discriminating result. +5. **Relay a live card.** With two Proxmarks (or a BomberCat host/client pair), run the relay so a reader at the proxy end transacts with a card at the mole end [mendoza2020reblay][bombercatblog]. On the Proxmark, the `hf_reblay` standalone mode relays ISO 14443-A over Bluetooth. Expected: the reader completes a transaction with the remote card. **Measure the added latency** and check whether the reader still completes, this is the discriminating result. 6. **Test the magstripe fallback** (payment/legacy access only): with BomberCat MagSpoof / `samyk/magspoof`, emit captured track data to a magstripe reader [magspoof] and record whether the terminal accepts the swipe. @@ -206,7 +206,7 @@ BomberCat / RelayNFC is documented by Electronic Cats as a tool for auditing ban A representative access-control assessment (authorised, own credentials): -- An LF HID Prox badge fingerprinted with `lf search` exposed a Wiegand facility/card number; cloning it to a T5577 with `lf hid clone -w H10301 --fc --cn ` produced a badge the door reader accepted as the original — the reader trusted the Wiegand number with no card authentication. +- An LF HID Prox badge fingerprinted with `lf search` exposed a Wiegand facility/card number; cloning it to a T5577 with `lf hid clone -w H10301 --fc --cn ` produced a badge the door reader accepted as the original, the reader trusted the Wiegand number with no card authentication. - An HF MIFARE Classic 1k staff card was dumped after key recovery (RFSAM-RFID-CR-01); writing the dump to a Gen2 magic card with `hf mf restore --1k --uid -k -f ` reproduced the UID and all sectors, and the turnstile accepted the clone. - The same dump loaded into a ChameleonUltra slot opened the turnstile with **no card at all**, confirming emulation as well as cloning. @@ -224,6 +224,6 @@ Note: the clone/emulate observations above are a representative composite of wel Layered, in order of effectiveness against this control: -- **Developer (credential / chip choice).** Do not authenticate on UID or on a Crypto1-protected secret — both clone trivially. Use credentials with strong, mutually-authenticated crypto (MIFARE DESFire EV2/EV3 with diversified AES keys, or equivalent) so a dump is not enough to impersonate, and so emulation must defeat real card crypto. This neutralises cloning and emulation [pm3magic], but **not relay**, which forwards a genuine authenticated exchange. -- **Integrator (reader / protocol).** To stop relay, the reader side must bound the transaction in time or space: a tight round-trip timeout or, better, a distance-bounding protocol — the only mechanism that addresses relay's defeat of proximity [hancke2005relay][francis2010relay]. Disable the magnetic-stripe fallback wherever the deployment allows, since MagSpoof reinstates the weakest path [magspoof]. Require chip/contactless and reject magstripe for high-value transactions. +- **Developer (credential / chip choice).** Do not authenticate on UID or on a Crypto1-protected secret, both clone trivially. Use credentials with strong, mutually-authenticated crypto (MIFARE DESFire EV2/EV3 with diversified AES keys, or equivalent) so a dump is not enough to impersonate, and so emulation must defeat real card crypto. This neutralises cloning and emulation [pm3magic], but **not relay**, which forwards a genuine authenticated exchange. +- **Integrator (reader / protocol).** To stop relay, the reader side must bound the transaction in time or space: a tight round-trip timeout or, better, a distance-bounding protocol, the only mechanism that addresses relay's defeat of proximity [hancke2005relay][francis2010relay]. Disable the magnetic-stripe fallback wherever the deployment allows, since MagSpoof reinstates the weakest path [magspoof]. Require chip/contactless and reject magstripe for high-value transactions. - **Operator (deployment / monitoring).** Treat UID and magstripe data as non-secret identifiers, never as proof of presence. Add backend anti-passback, geo/velocity and anomaly detection so a cloned or relayed credential used in two places, or with anomalous timing, is flagged. Where migration off legacy credentials is impossible, assume the credential is cloneable and compensate at the backend. diff --git a/src/content/controls/rfsam-rfid-cr-01.md b/src/content/controls/rfsam-rfid-cr-01.md index 8ac8450..c99b0db 100644 --- a/src/content/controls/rfsam-rfid-cr-01.md +++ b/src/content/controls/rfsam-rfid-cr-01.md @@ -12,26 +12,26 @@ applicability: deferred: false objective: >- Determine whether the Crypto1 sector keys protecting an ISO 14443-A MIFARE - Classic credential can be recovered — card-only, with one known key, or from a - sniffed reader transaction — and therefore whether the credential is clonable. + Classic credential can be recovered, card-only, with one known key, or from a + sniffed reader transaction, and therefore whether the credential is clonable. intro: >- MIFARE Classic's proprietary Crypto1 cipher uses a 48-bit key and a weak LFSR-based PRNG, and is fundamentally broken. Depending on the card's nonce behaviour, sector keys are recoverable card-only (no reader needed), with one - known key, or from a captured reader authentication — making most Crypto1 + known key, or from a captured reader authentication, making most Crypto1 access systems effectively clonable. This control selects the applicable attack and recovers the keys; it is RFSAM-owned (RFID is near-field; there is no BSAM equivalent for this layer). prerequisites: hardware: - - 'A Proxmark3 (RDV4 or compatible, running the Iceman firmware) — the reference HF tool for both the cryptanalytic attacks and the dump' + - 'A Proxmark3 (RDV4 or compatible, running the Iceman firmware), the reference HF tool for both the cryptanalytic attacks and the dump' - 'Alternatively a libnfc-driven PN532 / ACR122U USB reader for the offline mfoc / mfcuk crackers, or a Chameleon Ultra for read/emulate' - 'A target MIFARE Classic card in the field, or physical access to a legitimate reader for the reader-side (mfkey) path' software: - 'pm3 client (Iceman): hf 14a info / hf mf info / autopwn / darkside / nested / hardnested / mf sim' - 'Or mfoc (nested) and mfcuk (darkside) on libnfc; mfkey32/mfkey64 for reader-side recovery' signal: - freq: 'HF 13.56 MHz (ISO 14443-A) — near-field, magnetically coupled; no far-field radiation to survey' + freq: 'HF 13.56 MHz (ISO 14443-A), near-field, magnetically coupled; no far-field radiation to survey' bandwidth: 'Subcarrier load modulation at 847.5 kHz (fc/16); ~106 kbit/s baseline data rate' modulation: 'Reader→card: 100% ASK with modified Miller coding. Card→reader: OOK load modulation of an 847.5 kHz subcarrier with Manchester coding (ISO 14443-A)' skill: intermediate @@ -43,7 +43,7 @@ attacks: preconditions: A MIFARE Classic card with the original weak (16-bit-LFSR) PRNG that leaks via NACK and nonce repetition; ineffective against truly-random-nonce EV1 / hardened cards. summary: >- Card-only key recovery exploiting the Crypto1 NACK parity leak and nonce - repetition — bootstraps the first key when no default key works. + repetition, bootstraps the first key when no default key works. - name: Nested attack refs: - garcia2009pickpocket @@ -55,7 +55,7 @@ attacks: - name: Static-nonce nested (statiCnested) refs: - proxmark3-iceman - impact: Recovers the remaining sector keys on a card that returns a constant tag nonce — the case where plain nested and darkside both fail — given one known key, which on these clones is almost always a default. + impact: Recovers the remaining sector keys on a card that returns a constant tag nonce, the case where plain nested and darkside both fail, given one known key, which on these clones is almost always a default. preconditions: 'A MIFARE Classic / Fudan clone whose PRNG returns a fixed nonce every authentication (hf mf info → "Static nonce... yes"), plus one known sector key; default keys are present on most such cards.' summary: >- Variant of the nested attack for static-nonce cards: with the tag nonce @@ -85,24 +85,24 @@ attacks: preconditions: The ability to sniff (or relay) a genuine reader authenticating to a real card for that sector; no card-only access needed. summary: >- Recovers a sector key from a sniffed reader authentication exchange using - the Crapto1 keystream-recovery technique — attacks the reader, not the card. + the Crapto1 keystream-recovery technique, attacks the reader, not the card. references: - key: garcia2008dismantling title: Dismantling MIFARE Classic authors: 'F. D. Garcia, G. de Koning Gans, R. Muijrers, P. van Rossum, R. Verdult, R. Wichers Schreur, B. Jacobs' - venue: 'ESORICS 2008, LNCS 5283, pp. 97–114' + venue: 'ESORICS 2008, LNCS 5283, pp. 97 to 114' year: 2008 url: 'http://www.cs.ru.nl/~rverdult/Dismantling_MIFARE_Classic-ESORICS_2008.pdf' type: paper - key: garcia2009pickpocket title: Wirelessly Pickpocketing a Mifare Classic Card authors: 'F. D. Garcia, P. van Rossum, R. Verdult, R. Wichers Schreur' - venue: 'IEEE Symposium on Security and Privacy (S&P) 2009, pp. 3–15' + venue: 'IEEE Symposium on Security and Privacy (S&P) 2009, pp. 3 to 15' year: 2009 url: 'https://doi.org/10.1109/SP.2009.6' type: paper - key: courtois2009darkside - title: 'The Dark Side of Security by Obscurity — and Cloning MiFare Classic Rail and Building Passes, Anywhere, Anytime' + title: 'The Dark Side of Security by Obscurity: and Cloning MiFare Classic Rail and Building Passes, Anywhere, Anytime' authors: N. T. Courtois venue: 'SECRYPT 2009 / IACR ePrint 2009/137' year: 2009 @@ -130,17 +130,17 @@ references: url: 'https://blog.quarkslab.com/mifare-classic-static-encrypted-nonce-and-backdoors.html' type: blog - key: proxmark3-iceman - title: Proxmark3 — Iceman fork (RfidResearchGroup) + title: Proxmark3, Iceman fork (RfidResearchGroup) venue: GitHub url: 'https://github.com/RfidResearchGroup/proxmark3' type: tool - key: mfoc-tool - title: 'mfoc — MIFARE Classic Offline Cracker (nested attack)' + title: 'mfoc: MIFARE Classic Offline Cracker (nested attack)' venue: GitHub (nfc-tools) url: 'https://github.com/nfc-tools/mfoc' type: tool - key: mfcuk-tool - title: 'mfcuk — MiFare Classic Universal toolKit (darkside attack)' + title: 'mfcuk: MiFare Classic Universal toolKit (darkside attack)' venue: GitHub (nfc-tools) url: 'https://github.com/nfc-tools/mfcuk' type: tool @@ -162,18 +162,18 @@ lastResearched: 2026-06-18 ## Mechanism -MIFARE Classic protects each sector with a pair of 48-bit Crypto1 keys (A and B) and authenticates with a three-pass challenge-response. The cipher and its protocol were reverse-engineered and fully dismantled in 2008: Crypto1 is a 48-bit LFSR stream cipher with a non-linear filter, fed by a 16-bit LFSR card nonce, and the keystream leaks through the parity bits transmitted over the air [`garcia2008dismantling`]. That parity leak, plus the predictability of the card nonce, is what every Crypto1 attack exploits — the 48-bit key space is never brute-forced directly. +MIFARE Classic protects each sector with a pair of 48-bit Crypto1 keys (A and B) and authenticates with a three-pass challenge-response. The cipher and its protocol were reverse-engineered and fully dismantled in 2008: Crypto1 is a 48-bit LFSR stream cipher with a non-linear filter, fed by a 16-bit LFSR card nonce, and the keystream leaks through the parity bits transmitted over the air [`garcia2008dismantling`]. That parity leak, plus the predictability of the card nonce, is what every Crypto1 attack exploits, the 48-bit key space is never brute-forced directly. The applicable attack depends on the card's nonce behaviour, so the first job of this control is to classify it: - **Original weak PRNG (most legacy 1K/4K).** The card nonce comes from a 16-bit LFSR that the reader can advance to a known value, and the card leaks a NACK on bad parity. The **darkside** attack uses these two leaks to recover a first key card-only, with no reader and no prior key, in a few minutes [`courtois2009darkside`]. Once any one key is known, the **nested** attack triggers sector-to-sector ("nested") authentications and recovers every remaining key from the encrypted-nonce parity leak [`garcia2009pickpocket`]. -- **Static nonce (many Fudan-based clones).** Some MIFARE-compatible cards return a *constant* tag nonce on every authentication. A fixed nonce defeats both darkside and the plain nested attack — each needs the nonce to vary to correlate keystream — but it does not save the card: given one known sector key (default keys are almost always present on these clones), the **staticnested** attack derives the candidate keys consistent with that constant nonce and verifies them against the card, recovering the remaining sectors in seconds [`proxmark3-iceman`]. `hf mf info` flags this case as `Static nonce... yes`; do not confuse it with the *static encrypted nonce* of the FM11RF08S below, which prints differently and is a separate attack. +- **Static nonce (many Fudan-based clones).** Some MIFARE-compatible cards return a *constant* tag nonce on every authentication. A fixed nonce defeats both darkside and the plain nested attack, each needs the nonce to vary to correlate keystream, but it does not save the card: given one known sector key (default keys are almost always present on these clones), the **staticnested** attack derives the candidate keys consistent with that constant nonce and verifies them against the card, recovering the remaining sectors in seconds [`proxmark3-iceman`]. `hf mf info` flags this case as `Static nonce... yes`; do not confuse it with the *static encrypted nonce* of the FM11RF08S below, which prints differently and is a separate attack. - **Hardened PRNG (MIFARE Classic EV1 and hardened clones).** These emit truly-random nonces, defeating darkside and plain nested. The **hardnested** attack is a ciphertext-only statistical cryptanalysis that, given one known key, collects encrypted nonces and reduces the search from 2^48 to roughly 2^30, recovering a key in about five minutes on a single laptop core [`meijer2015hardnested`]. - **Static encrypted nonce (Fudan FM11RF08S and relatives).** A 2020-era "MIFARE-compatible" variant added a static-encrypted-nonce countermeasure specifically to thwart all known card-only attacks. In 2024 this was broken, and a **hardware backdoor key common to all FM11RF08S cards** was recovered: anyone who knows it can authenticate to and dump user sectors without the user keys, in a few minutes of card access [`teuwen2024fm11rf08s`, `teuwen2024blog`]. -There is also a reader-side path. When a genuine reader is observed authenticating to a real card, **mfkey32** recovers a sector key from two authentication attempts on the same nonce, and **mfkey64** from a single full authentication — both reconstruct the Crypto1 state from the captured (encrypted) handshake rather than touching the card [`garcia2008dismantling`]. This is the route when the card itself is out of reach but a reader is not. +There is also a reader-side path. When a genuine reader is observed authenticating to a real card, **mfkey32** recovers a sector key from two authentication attempts on the same nonce, and **mfkey64** from a single full authentication, both reconstruct the Crypto1 state from the captured (encrypted) handshake rather than touching the card [`garcia2008dismantling`]. This is the route when the card itself is out of reach but a reader is not. -A practical shortcut precedes all of the above: enormous numbers of deployments never change the transport keys, so a **default/dictionary key check** (`FFFFFFFFFFFF`, `A0A1A2A3A4A5`, …) frequently recovers keys with no cryptanalysis at all. RFID is near-field and RFSAM-owned at this layer; LF tags and DESFire/AES cards are out of scope for these attacks — recognise them and stop, per the Wayfinder. +A practical shortcut precedes all of the above: enormous numbers of deployments never change the transport keys, so a **default/dictionary key check** (`FFFFFFFFFFFF`, `A0A1A2A3A4A5`, …) frequently recovers keys with no cryptanalysis at all. RFID is near-field and RFSAM-owned at this layer; LF tags and DESFire/AES cards are out of scope for these attacks, recognise them and stop, per the Wayfinder. ## Procedure @@ -184,21 +184,21 @@ All steps below are active interrogation of a credential. Run them only against [usb] pm3 --> hf 14a info [usb] pm3 --> hf mf info ``` - Expected: `hf 14a info` prints the UID, SAK, ATQA and the chip guess (e.g. *MIFARE Classic 1K*). `hf mf info` reports the PRNG / nonce class — read it as **weak** (`darkside`/`nested`), **static nonce** (`Static nonce... yes` → `staticnested`), **hardened/random** (`hardnested`), or **static *encrypted* nonce** (FM11RF08S techniques). It also fingerprints the chip (e.g. *Fudan based card*) and surfaces any sector already on a default key. Note whether the UID is 4-byte or 7-byte and whether the card is a known Fudan clone. + Expected: `hf 14a info` prints the UID, SAK, ATQA and the chip guess (e.g. *MIFARE Classic 1K*). `hf mf info` reports the PRNG / nonce class, read it as **weak** (`darkside`/`nested`), **static nonce** (`Static nonce... yes` → `staticnested`), **hardened/random** (`hardnested`), or **static *encrypted* nonce** (FM11RF08S techniques). It also fingerprints the chip (e.g. *Fudan based card*) and surfaces any sector already on a default key. Note whether the UID is 4-byte or 7-byte and whether the card is a known Fudan clone. 2. **Try default and dictionary keys first.** Many systems never change them: ``` [usb] pm3 --> hf mf chk *1 ? d ``` - Expected: a per-sector table of recovered keys A/B. If every sector resolves here, skip straight to step 6 — no cryptanalysis was needed (a finding in itself). + Expected: a per-sector table of recovered keys A/B. If every sector resolves here, skip straight to step 6, no cryptanalysis was needed (a finding in itself). -3. **Run the matching card-only attack.** Let `hf mf autopwn` orchestrate the chain — it reads the PRNG class from step 1, tries the dictionary, and picks the attack per sector. The explicit single-attack forms are also shown: +3. **Run the matching card-only attack.** Let `hf mf autopwn` orchestrate the chain, it reads the PRNG class from step 1, tries the dictionary, and picks the attack per sector. The explicit single-attack forms are also shown: ``` [usb] pm3 --> hf mf autopwn - [usb] pm3 --> hf mf darkside # weak PRNG, no known key — bootstrap a first key - [usb] pm3 --> hf mf staticnested --1k --blk 0 -a -k FFFFFFFFFFFF # static nonce — seed from a known key + [usb] pm3 --> hf mf darkside # weak PRNG, no known key, bootstrap a first key + [usb] pm3 --> hf mf staticnested --1k --blk 0 -a -k FFFFFFFFFFFF # static nonce, seed from a known key ``` - Expected: for a **weak-PRNG** card with no known key, `darkside` returns a first key in a few minutes and `autopwn` then chains nested → key-table → dump. For a **static-nonce** card (most Fudan clones — `hf mf info` printed `Static nonce... yes`), darkside and plain nested do not apply; `autopwn` seeds from any default key it finds and runs `staticnested` for the rest. Read *which* attack actually recovered each key from the result column of the key table — the legend is `D`:dictionary · `S`:darkside · `N`:nested · `H`:hardnested · **`C`:statiCnested** · `R`:reused · `U`:user. Offline tools on a PN532/ACR122U cover only the weak path: `mfoc -O dump.mfd` (nested, needs one known/default key) or `mfcuk -C -R 0:A -s 250 -S 250` (darkside) — neither implements the static-nonce attack, so a static-nonce card needs the Proxmark. + Expected: for a **weak-PRNG** card with no known key, `darkside` returns a first key in a few minutes and `autopwn` then chains nested → key-table → dump. For a **static-nonce** card (most Fudan clones, `hf mf info` printed `Static nonce... yes`), darkside and plain nested do not apply; `autopwn` seeds from any default key it finds and runs `staticnested` for the rest. Read *which* attack actually recovered each key from the result column of the key table, the legend is `D`:dictionary · `S`:darkside · `N`:nested · `H`:hardnested · **`C`:statiCnested** · `R`:reused · `U`:user. Offline tools on a PN532/ACR122U cover only the weak path: `mfoc -O dump.mfd` (nested, needs one known/default key) or `mfcuk -C -R 0:A -s 250 -S 250` (darkside), neither implements the static-nonce attack, so a static-nonce card needs the Proxmark. 4. **For hardened (EV1 / hard-PRNG) cards, use hardnested with one known key.** If a default key was found for any sector in step 2, recover the rest: ``` @@ -219,13 +219,13 @@ All steps below are active interrogation of a credential. Run them only against [usb] pm3 --> hf mf dump [usb] pm3 --> hf mf autopwn # also writes the dump + keyfile ``` - Expected: a full `*.bin` / `*.eml` dump plus the recovered key file. Parse it (e.g. `mfdread`) to read the access-control payload (facility/card number, value blocks). If all keys are recovered, the credential is clonable — to a magic Gen1a/Gen2 card or emulated from a Chameleon Ultra (see RFSAM-RES-14). Recovering the keys here, not the clone, is the finding this control records. + Expected: a full `*.bin` / `*.eml` dump plus the recovered key file. Parse it (e.g. `mfdread`) to read the access-control payload (facility/card number, value blocks). If all keys are recovered, the credential is clonable, to a magic Gen1a/Gen2 card or emulated from a Chameleon Ultra (see RFSAM-RES-14). Recovering the keys here, not the clone, is the finding this control records. ## Field case -Real capture — a Fudan-based MIFARE Classic 1K clone (FNUID, fixed UID) on the bench, decrypted end-to-end with a Proxmark3 (Iceman) in 37 seconds. This is the **static-nonce** branch above, demonstrated. +Real capture, a Fudan-based MIFARE Classic 1K clone (FNUID, fixed UID) on the bench, decrypted end-to-end with a Proxmark3 (Iceman) in 37 seconds. This is the **static-nonce** branch above, demonstrated. -1. `hf mf info` fingerprinted it as a **Fudan based card**, Classic 1K — UID `8F 05 E5 D8`, ATQA `0004`, SAK `08`, block 0 `8F05E5D8B70804006263646566676869` (the trailing `6263646566676869` is ASCII `bcdefghi`, the placeholder manufacturer bytes these clones ship with). The PRNG section reported a **plain static nonce**, not a static *encrypted* nonce, and sector 0 already authenticated with the transport default: +1. `hf mf info` fingerprinted it as a **Fudan based card**, Classic 1K, UID `8F 05 E5 D8`, ATQA `0004`, SAK `08`, block 0 `8F05E5D8B70804006263646566676869` (the trailing `6263646566676869` is ASCII `bcdefghi`, the placeholder manufacturer bytes these clones ship with). The PRNG section reported a **plain static nonce**, not a static *encrypted* nonce, and sector 0 already authenticated with the transport default: ``` [#] Static nonce....... 01200145 [+] Static nonce... yes @@ -233,12 +233,12 @@ Real capture — a Fudan-based MIFARE Classic 1K clone (FNUID, fixed UID) on the [+] Sector 0 key B... FFFFFFFFFFFF ``` -2. `hf mf autopwn` recovered every key in one pass. The dictionary resolved 15 of the 16 sectors (0 and 2–15, A and B) to the default `FFFFFFFFFFFF`. Sector 1 held a non-default key and fell to **staticnested** — autopwn derived `59578` candidate keys consistent with the static nonce, verified them online at ~160 keys/s, and hit the valid one inside the first thousand: +2. `hf mf autopwn` recovered every key in one pass. The dictionary resolved 15 of the 16 sectors (0 and 2 to 15, A and B) to the default `FFFFFFFFFFFF`. Sector 1 held a non-default key and fell to **staticnested**, autopwn derived `59578` candidate keys consistent with the static nonce, verified them online at ~160 keys/s, and hit the valid one inside the first thousand: ``` [+] target block 4 key type A -- found valid key [ 8A19D40CF2B5 ] [+] Target sector 1 key type A -- found valid key [ 8A19D40CF2B5 ] ``` - The result column confirms which attack recovered each sector — `D` (dictionary) for the 15 default sectors, **`C` (statiCnested)** for sector 1: + The result column confirms which attack recovered each sector, `D` (dictionary) for the 15 default sectors, **`C` (statiCnested)** for sector 1: ``` [+] Sec | Blk | key A |res| key B |res [+] 000 | 003 | FFFFFFFFFFFF | D | FFFFFFFFFFFF | D @@ -255,7 +255,7 @@ Real capture — a Fudan-based MIFARE Classic 1K clone (FNUID, fixed UID) on the [=] Autopwn execution time: 37 seconds ``` -4. Reading the dump back (`hf mf dump`, then `hf mf view`) shows *why* the static-nonce attack earned its keep: the one key that wasn't the default — sector 1's `8A19D40CF2B5` — also guards the only sector on the card that holds data. Its trailer carries the recovered key in situ, and blocks 4–6 are the only non-zero bytes anywhere on the card: +4. Reading the dump back (`hf mf dump`, then `hf mf view`) shows *why* the static-nonce attack earned its keep: the one key that wasn't the default, sector 1's `8A19D40CF2B5`, also guards the only sector on the card that holds data. Its trailer carries the recovered key in situ, and blocks 4 to 6 are the only non-zero bytes anywhere on the card: ``` [=] sec | blk | data | ascii [=] 0 | 0 | 8F 05 E5 D8 B7 08 04 00 62 63 64 65 66 67 68 69 | ........bcdefghi @@ -264,11 +264,11 @@ Real capture — a Fudan-based MIFARE Classic 1K clone (FNUID, fixed UID) on the [=] | 6 | 9E 84 FF 6D 03 BE 00 00 00 00 00 00 00 00 00 00 | ...m............ [=] | 7 | 8A 19 D4 0C F2 B5 FF 07 80 69 8A 19 D4 0C F2 B5 | .........i...... ``` - Block 7 is sector 1's trailer: key A `8A19D40CF2B5`, access bits `FF 07 80`, GPB `69`, key B `8A19D40CF2B5` — the staticnested-recovered key, now readable on the card. Every other sector (0, 2–15) is blank data behind the default trailer `FF FF FF FF FF FF FF 07 80 69 FF FF FF FF FF FF`. The sector-1 bytes are an opaque application payload — recorded as captured, not interpreted. + Block 7 is sector 1's trailer: key A `8A19D40CF2B5`, access bits `FF 07 80`, GPB `69`, key B `8A19D40CF2B5`, the staticnested-recovered key, now readable on the card. Every other sector (0, 2 to 15) is blank data behind the default trailer `FF FF FF FF FF FF FF 07 80 69 FF FF FF FF FF FF`. The sector-1 bytes are an opaque application payload, recorded as captured, not interpreted. -The finding this records: **every Crypto1 key on a real Classic 1K recovered card-only in 37 seconds** — 15 sectors still on the transport default, and the one non-default key (`8A19D40CF2B5`) recovered by the static-nonce nested attack that plain nested and darkside cannot perform. The card offers no cryptographic protection; with the keys and dump in hand it is fully clonable to a magic Gen1a/Gen2 card or emulated from a Chameleon Ultra (see RFSAM-RES-14). The other nonce classes differ only in the attack chosen: a weak-PRNG card with no default key starts with `hf mf darkside`; a hardened EV1 card uses `hf mf hardnested` seeded with one known key, recovering a target key in about five minutes [`meijer2015hardnested`]; an FM11RF08S clone instead falls to the static-*encrypted*-nonce techniques and the shared hardware backdoor key [`teuwen2024fm11rf08s`]. +The finding this records: **every Crypto1 key on a real Classic 1K recovered card-only in 37 seconds**, 15 sectors still on the transport default, and the one non-default key (`8A19D40CF2B5`) recovered by the static-nonce nested attack that plain nested and darkside cannot perform. The card offers no cryptographic protection; with the keys and dump in hand it is fully clonable to a magic Gen1a/Gen2 card or emulated from a Chameleon Ultra (see RFSAM-RES-14). The other nonce classes differ only in the attack chosen: a weak-PRNG card with no default key starts with `hf mf darkside`; a hardened EV1 card uses `hf mf hardnested` seeded with one known key, recovering a target key in about five minutes [`meijer2015hardnested`]; an FM11RF08S clone instead falls to the static-*encrypted*-nonce techniques and the shared hardware backdoor key [`teuwen2024fm11rf08s`]. -**A second card makes that last branch concrete — a genuine FM11RF08S.** This case is reconstructed from the saved dump and keyfile, not a live console log (the card was no longer on hand to re-capture the run); the recovery itself is what the artifacts prove — the FM11RF08S tool's `…-nonces_with_data.json` plus a complete 1 KB dump with every key resolved. It reads as a Classic 1K — UID `E2 96 C1 9A`, SAK `08`, ATQA `0004`, block 0 `E296C19A 2F 08 0400 0544FDD8A539F490` — but two things mark it as an FM11RF08S rather than the all-default clone above: the manufacturer bytes are *real* (`0544FDD8A539F490`, not the `bcdefghi` placeholder), and it carries the extra hidden config sector only that chip has. Unlike the Fudan card, it is genuinely keyed — diversified non-default keys on several sectors, with non-default access bits: +**A second card makes that last branch concrete, a genuine FM11RF08S.** This case is reconstructed from the saved dump and keyfile, not a live console log (the card was no longer on hand to re-capture the run); the recovery itself is what the artifacts prove, the FM11RF08S tool's `…-nonces_with_data.json` plus a complete 1 KB dump with every key resolved. It reads as a Classic 1K, UID `E2 96 C1 9A`, SAK `08`, ATQA `0004`, block 0 `E296C19A 2F 08 0400 0544FDD8A539F490`, but two things mark it as an FM11RF08S rather than the all-default clone above: the manufacturer bytes are *real* (`0544FDD8A539F490`, not the `bcdefghi` placeholder), and it carries the extra hidden config sector only that chip has. Unlike the Fudan card, it is genuinely keyed, diversified non-default keys on several sectors, with non-default access bits: ``` sec | key A | key B | access | note @@ -276,11 +276,11 @@ sec | key A | key B | access | note 1 | D203A62D6106 | 602A34A75AA4 | 787788 | both non-default 2 | A0A1A2A3A4A5 | 0000014B5C31 | 0F00FF | key B non-default 6 | FFFFFFFFFFFF | 96A301BCE267 | 0F00FF | key B non-default - 3–5, 7–15 | default FFFFFFFFFFFF / FFFFFFFFFFFF + 3 to 5, 7 to 15 | default FFFFFFFFFFFF / FFFFFFFFFFFF hidden config sector | key A 3E64977BDF58 | key B 00005BF0055A ``` -Those keys are not guessable and there is no weak or predictable nonce to attack — the static-encrypted-nonce countermeasure was built specifically to defeat darkside, nested and hardnested alike. The FM11RF08S break sidesteps all three: a hardware backdoor key shared across the product line authenticates to the sectors without the user keys, exposes each sector's static encrypted nonce (the values the `nonces_with_data.json` recorded), and from those the user keys fall in a few minutes of card access [`teuwen2024fm11rf08s`, `teuwen2024blog`]. The saved artifacts are exactly that outcome — all 16 sector keys plus the hidden sector recovered, and the full 1 KB read, including the high-entropy sector-1 payload that was only readable once its non-default keys fell: +Those keys are not guessable and there is no weak or predictable nonce to attack, the static-encrypted-nonce countermeasure was built specifically to defeat darkside, nested and hardnested alike. The FM11RF08S break sidesteps all three: a hardware backdoor key shared across the product line authenticates to the sectors without the user keys, exposes each sector's static encrypted nonce (the values the `nonces_with_data.json` recorded), and from those the user keys fall in a few minutes of card access [`teuwen2024fm11rf08s`, `teuwen2024blog`]. The saved artifacts are exactly that outcome, all 16 sector keys plus the hidden sector recovered, and the full 1 KB read, including the high-entropy sector-1 payload that was only readable once its non-default keys fell: ``` blk 4 (sec 1): 0B54C20A3DD92C5DC8E72B430EA01D9A @@ -288,12 +288,12 @@ blk 5 (sec 1): E565FA30CF15A6DEA2D4F0B734028E7F blk 6 (sec 1): 409B343083DE680526A03200FEFD0EA2 ``` -The finding this second case records: *a card sold as a hardened, non-cloneable MIFARE Classic — real diversified keys, non-default access bits, the static-encrypted-nonce defence — still surrenders every key to the shared FM11RF08S backdoor.* That is the whole lesson of the FM11RF08S story, and the reason the remediation below is the same for it as for the trivial clone: no Crypto1-compatible countermeasure, not even this one, has held. +The finding this second case records: *a card sold as a hardened, non-cloneable MIFARE Classic, real diversified keys, non-default access bits, the static-encrypted-nonce defence, still surrenders every key to the shared FM11RF08S backdoor.* That is the whole lesson of the FM11RF08S story, and the reason the remediation below is the same for it as for the trivial clone: no Crypto1-compatible countermeasure, not even this one, has held. ## Remediation -**Developer / product team.** Do not design new systems on MIFARE Classic or any Crypto1-compatible card (including MIFARE Plus operated in SL1 and "MIFARE-compatible" clones). Crypto1 is broken by design — a 48-bit key with a parity keystream leak — and no card-only countermeasure has held: even the static-encrypted-nonce FM11RF08S fell and shipped with a shared hardware backdoor [`teuwen2024fm11rf08s`]. Specify audited cryptographic credentials (MIFARE DESFire EV2/EV3 with AES, or equivalent) with per-card diversified keys and challenge-response that binds to card-authenticated data, not to the UID. +**Developer / product team.** Do not design new systems on MIFARE Classic or any Crypto1-compatible card (including MIFARE Plus operated in SL1 and "MIFARE-compatible" clones). Crypto1 is broken by design, a 48-bit key with a parity keystream leak, and no card-only countermeasure has held: even the static-encrypted-nonce FM11RF08S fell and shipped with a shared hardware backdoor [`teuwen2024fm11rf08s`]. Specify audited cryptographic credentials (MIFARE DESFire EV2/EV3 with AES, or equivalent) with per-card diversified keys and challenge-response that binds to card-authenticated data, not to the UID. -**Integrator.** Never authorise on UID alone — UIDs are freely clonable to magic cards regardless of Crypto1. If a Crypto1 deployment cannot be replaced immediately, at minimum change all transport/default keys (a default key collapses the entire attack chain to step 2), use both A and B keys with least-privilege access bits, and plan migration; treat every Crypto1 sector key as recoverable by an attacker with a few minutes of card or reader access. +**Integrator.** Never authorise on UID alone, UIDs are freely clonable to magic cards regardless of Crypto1. If a Crypto1 deployment cannot be replaced immediately, at minimum change all transport/default keys (a default key collapses the entire attack chain to step 2), use both A and B keys with least-privilege access bits, and plan migration; treat every Crypto1 sector key as recoverable by an attacker with a few minutes of card or reader access. -**Operator.** Assume any Crypto1 badge in your environment is clonable and act at the backend: enable anti-passback and impossible-travel / velocity anomaly detection, log and alert on duplicate-UID or out-of-sequence reads, and shorten credential lifetimes. These do not fix the card — they detect use of a clone after the keys are gone — so prioritise migration off Crypto1 over compensating controls. +**Operator.** Assume any Crypto1 badge in your environment is clonable and act at the backend: enable anti-passback and impossible-travel / velocity anomaly detection, log and alert on duplicate-UID or out-of-sequence reads, and shorten credential lifetimes. These do not fix the card, they detect use of a clone after the keys are gone, so prioritise migration off Crypto1 over compensating controls. diff --git a/src/content/controls/rfsam-rfid-sp-01.md b/src/content/controls/rfsam-rfid-sp-01.md index 8b1900a..f622054 100644 --- a/src/content/controls/rfsam-rfid-sp-01.md +++ b/src/content/controls/rfsam-rfid-sp-01.md @@ -14,13 +14,13 @@ objective: >- Determine, before any crypto or cloning step, which carrier band a credential uses (LF 125/134 kHz vs HF 13.56 MHz), which standard/chip family it is (EM4100/HID Prox; ISO/IEC 14443 MIFARE Classic/Ultralight/DESFire/NTAG; - ISO/IEC 15693), and — for MIFARE Classic — whether its nonce/PRNG behaviour is + ISO/IEC 15693), and, for MIFARE Classic, whether its nonce/PRNG behaviour is weak, hardened or static, so the correct downstream attack path can be chosen. intro: >- RFID/NFC has no far-field spectrum to survey: LF and HF are near-field (magnetically coupled), so "see it" means powering the tag in the reader's field and reading back its carrier, standard and chip. That identification is - the fork that decides the entire assessment — a Crypto1 attack is meaningless + the fork that decides the entire assessment, a Crypto1 attack is meaningless against DESFire AES, and an LF EM4100 ID needs no cracking at all. prerequisites: hardware: @@ -29,7 +29,7 @@ prerequisites: - 'Proxmark3 client (pm3, Iceman fork) for lf/hf search and hf mf info; ChameleonUltra GUI for a pocket read' signal: freq: 'LF 125/134 kHz · HF 13.56 MHz' - bandwidth: 'Near-field, magnetically coupled — no far-field radiation to survey' + bandwidth: 'Near-field, magnetically coupled, no far-field radiation to survey' modulation: 'LF: ASK/OOK or FSK load modulation. HF: ASK with Manchester/Miller subcarrier load modulation (ISO/IEC 14443), or the ISO/IEC 15693 vicinity air interface.' skill: beginner attacks: @@ -57,8 +57,8 @@ attacks: - name: Hardnested (hardened-card ciphertext-only attack) refs: - meijer2015hardnested - impact: Recovers keys from "hardened" MIFARE Classic (e.g. EV1) that resist the plain nested attack, using ~1600–2200 nonces. - preconditions: Card identified as a hardened MIFARE Classic — exactly the weak-vs-hardened-vs-static classification this control records. + impact: Recovers keys from "hardened" MIFARE Classic (e.g. EV1) that resist the plain nested attack, using ~1600 to 2200 nonces. + preconditions: Card identified as a hardened MIFARE Classic, exactly the weak-vs-hardened-vs-static classification this control records. summary: >- Ciphertext-only cryptanalysis defeating the PRNG hardening; the identification step's nonce classification (weak/hard/static) selects this @@ -79,7 +79,7 @@ references: url: 'https://doi.org/10.1109/SP.2009.6' type: paper - key: courtois2009darkside - title: 'The Dark Side of Security by Obscurity — and Cloning MiFare Classic Rail and Building Passes, Anywhere, Anytime' + title: 'The Dark Side of Security by Obscurity: and Cloning MiFare Classic Rail and Building Passes, Anywhere, Anytime' authors: N. T. Courtois venue: SECRYPT 2009 year: 2009 @@ -93,26 +93,26 @@ references: url: 'https://doi.org/10.1145/2810103.2813641' type: paper - key: iso14443-1 - title: 'ISO/IEC 14443-1:2018 — Cards and security devices for personal identification — Contactless proximity objects — Part 1: Physical characteristics' + title: 'ISO/IEC 14443-1:2018: Cards and security devices for personal identification: Contactless proximity objects: Part 1: Physical characteristics' venue: ISO/IEC year: 2018 url: 'https://www.iso.org/standard/73596.html' type: standard - key: iso15693-1 - title: 'ISO/IEC 15693-1:2018 — Cards and security devices for personal identification — Contactless vicinity objects — Part 1: Physical characteristics' + title: 'ISO/IEC 15693-1:2018: Cards and security devices for personal identification: Contactless vicinity objects: Part 1: Physical characteristics' venue: ISO/IEC year: 2018 url: 'https://www.iso.org/standard/70837.html' type: standard - key: pm3-iceman - title: 'Proxmark3 (Iceman fork) — RfidResearchGroup/proxmark3, client command reference' + title: 'Proxmark3 (Iceman fork): RfidResearchGroup/proxmark3, client command reference' authors: RFID Research Group (Iceman) venue: GitHub year: 2026 url: 'https://github.com/RfidResearchGroup/proxmark3/blob/master/doc/commands.md' type: tool - key: pm3-mfkey-examples - title: 'Proxmark3 (Iceman fork) — tools/mfc/card_reader/mfkey_examples.md, sample MIFARE Classic trace' + title: 'Proxmark3 (Iceman fork): tools/mfc/card_reader/mfkey_examples.md, sample MIFARE Classic trace' authors: RFID Research Group (Iceman) venue: GitHub year: 2026 @@ -131,11 +131,11 @@ lastResearched: 2026-06-14 --- ## Mechanism -RFID/NFC operates in two near-field bands that do not radiate to the far field, so unlike Wi-Fi or Sub-GHz there is no spectrum to sweep with an SDR: the reader is the instrument, and "seeing" a tag means energising it in the reader's magnetic field and reading back its carrier, standard and chip. The two bands are **LF 125/134 kHz** (EM4100/EM4102, HID Prox, Indala, HITAG, T5577 — mostly fixed read-only IDs with little or no crypto) and **HF 13.56 MHz**, where ISO/IEC 14443-A/B governs proximity cards (MIFARE Classic/Ultralight, NTAG, DESFire, contactless EMV) [iso14443-1] and ISO/IEC 15693 governs vicinity cards (iCODE) [iso15693-1]. The carrier band is the first fork, because it decides every tool choice and the entire downstream attack tree. +RFID/NFC operates in two near-field bands that do not radiate to the far field, so unlike Wi-Fi or Sub-GHz there is no spectrum to sweep with an SDR: the reader is the instrument, and "seeing" a tag means energising it in the reader's magnetic field and reading back its carrier, standard and chip. The two bands are **LF 125/134 kHz** (EM4100/EM4102, HID Prox, Indala, HITAG, T5577, mostly fixed read-only IDs with little or no crypto) and **HF 13.56 MHz**, where ISO/IEC 14443-A/B governs proximity cards (MIFARE Classic/Ultralight, NTAG, DESFire, contactless EMV) [iso14443-1] and ISO/IEC 15693 governs vicinity cards (iCODE) [iso15693-1]. The carrier band is the first fork, because it decides every tool choice and the entire downstream attack tree. -The second fork is the chip family and its security mode, and it is decisive because the named attacks apply only to specific families. **MIFARE Classic** authenticates with the proprietary 48-bit Crypto1 stream cipher, which was reverse-engineered and shown breakable: the cipher and protocol were dismantled and key-recovery attacks demonstrated [garcia2008dismantling], and the "nested" attack recovers all remaining sector keys once any single key is known [garcia2009pickpocketing]. A **card-only** "darkside" attack recovers a first key from the card alone, with no known key and no legitimate reader, on cards whose pseudo-random nonce generator is exploitable [courtois2009darkside]; **hardened** MIFARE Classic (e.g. EV1) that resists the plain nested attack still falls to a **ciphertext-only** "hardnested" attack using roughly 1600–2200 collected nonces [meijer2015hardnested]. By contrast, LF EM4100/HID IDs carry no cryptographic secret to recover, and DESFire EV1/2/3 and modern NTAG (AES/3DES) are out of scope for the Crypto1 family entirely — so identifying the chip and its PRNG behaviour up front tells you which, if any, of these paths even applies. +The second fork is the chip family and its security mode, and it is decisive because the named attacks apply only to specific families. **MIFARE Classic** authenticates with the proprietary 48-bit Crypto1 stream cipher, which was reverse-engineered and shown breakable: the cipher and protocol were dismantled and key-recovery attacks demonstrated [garcia2008dismantling], and the "nested" attack recovers all remaining sector keys once any single key is known [garcia2009pickpocketing]. A **card-only** "darkside" attack recovers a first key from the card alone, with no known key and no legitimate reader, on cards whose pseudo-random nonce generator is exploitable [courtois2009darkside]; **hardened** MIFARE Classic (e.g. EV1) that resists the plain nested attack still falls to a **ciphertext-only** "hardnested" attack using roughly 1600 to 2200 collected nonces [meijer2015hardnested]. By contrast, LF EM4100/HID IDs carry no cryptographic secret to recover, and DESFire EV1/2/3 and modern NTAG (AES/3DES) are out of scope for the Crypto1 family entirely, so identifying the chip and its PRNG behaviour up front tells you which, if any, of these paths even applies. -This control is the SP-layer identification step that records that fork. For MIFARE Classic specifically, it also classifies the nonce/PRNG behaviour (weak vs hardened vs static), because that classification selects darkside vs nested vs hardnested vs staticnested downstream [courtois2009darkside][meijer2015hardnested]. The Iceman `hf mf info` PRNG section reports this directly — `Prng....... weak`, `Prng....... hard`, or `Static nonce... yes` / `Static enc nonce... yes` for the respective classes [pm3-iceman]. There is also a passive identification path: when a legitimate reader and card are already transacting, the reader can sniff that exchange without transmitting, reading the standard and UID off a genuine transaction. +This control is the SP-layer identification step that records that fork. For MIFARE Classic specifically, it also classifies the nonce/PRNG behaviour (weak vs hardened vs static), because that classification selects darkside vs nested vs hardnested vs staticnested downstream [courtois2009darkside][meijer2015hardnested]. The Iceman `hf mf info` PRNG section reports this directly, `Prng....... weak`, `Prng....... hard`, or `Static nonce... yes` / `Static enc nonce... yes` for the respective classes [pm3-iceman]. There is also a passive identification path: when a legitimate reader and card are already transacting, the reader can sniff that exchange without transmitting, reading the standard and UID off a genuine transaction. ## Procedure @@ -145,13 +145,13 @@ All steps below are authorised-testing steps: run them only against cards you ow ``` pm3 --> lf search ``` - A 125 kHz tag reports its standard and decoded ID, e.g. `Valid EM410x ID found!` with the 40-bit ID, or `Valid HID Prox ID found!` with the facility/card number. "No known 125/134 kHz tags found" means it is not an LF credential — move to HF. [pm3-iceman] + A 125 kHz tag reports its standard and decoded ID, e.g. `Valid EM410x ID found!` with the 40-bit ID, or `Valid HID Prox ID found!` with the facility/card number. "No known 125/134 kHz tags found" means it is not an LF credential, move to HF. [pm3-iceman] 2. **Identify the HF band.** Place the card on the HF antenna and run: ``` pm3 --> hf search ``` - This fingerprints the standard and chip — e.g. `Valid ISO 14443-A tag found` with the UID, SAK, ATQA and a chip guess (MIFARE Classic 1K, MIFARE Ultralight, NTAG21x, MIFARE DESFire), or an `ISO 15693` / iCODE match. The reported SAK/ATQA and chip guess are the fork: Classic → Crypto1 path; DESFire/NTAG → strong crypto, stop. [pm3-iceman][iso14443-1] + This fingerprints the standard and chip, e.g. `Valid ISO 14443-A tag found` with the UID, SAK, ATQA and a chip guess (MIFARE Classic 1K, MIFARE Ultralight, NTAG21x, MIFARE DESFire), or an `ISO 15693` / iCODE match. The reported SAK/ATQA and chip guess are the fork: Classic → Crypto1 path; DESFire/NTAG → strong crypto, stop. [pm3-iceman][iso14443-1] 3. **Classify the MIFARE Classic PRNG (only if step 2 says Classic).** Read the card's nonce/PRNG behaviour: ``` @@ -165,13 +165,13 @@ All steps below are authorised-testing steps: run them only against cards you ow ``` pm3 --> hf 14a sniff ``` - Read the standard, the UID and the command traffic off the reader's own field — adding no field of your own. (A pocket alternative: a ChameleonUltra GUI or BomberCat HF field-read identifies the card when no Proxmark is to hand.) + Read the standard, the UID and the command traffic off the reader's own field, adding no field of your own. (A pocket alternative: a ChameleonUltra GUI or BomberCat HF field-read identifies the card when no Proxmark is to hand.) ## Field case -A sample MIFARE Classic trace shipped with Proxmark3 (RfidResearchGroup/proxmark3, `tools/mfc/card_reader/mfkey_examples.md`, "Sample trace") documents a genuine ISO/IEC 14443-A 1K card and makes the identification fork concrete [pm3-mfkey-examples]. In that trace the card's anticollision reply gives **ATQA `0004`** (`TAG 04 00`) and **SAK `08`** (`TAG 08 b6 dd`) — the MIFARE Classic 1K fingerprint — with UID **`9C599B32`** (`TAG 9c 59 9b 32 6c`). The repository's own usage line labels `9C599B32` as the card's `` and feeds the captured authentication nonces to mfkey64 to recover a Crypto1 sector key, i.e. it is a **weak-Crypto1 (attackable-PRNG) MIFARE Classic 1K** [pm3-mfkey-examples]. An LF pass over the same band would have returned nothing, since this is a 13.56 MHz HF credential, not a 125 kHz one. +A sample MIFARE Classic trace shipped with Proxmark3 (RfidResearchGroup/proxmark3, `tools/mfc/card_reader/mfkey_examples.md`, "Sample trace") documents a genuine ISO/IEC 14443-A 1K card and makes the identification fork concrete [pm3-mfkey-examples]. In that trace the card's anticollision reply gives **ATQA `0004`** (`TAG 04 00`) and **SAK `08`** (`TAG 08 b6 dd`), the MIFARE Classic 1K fingerprint, with UID **`9C599B32`** (`TAG 9c 59 9b 32 6c`). The repository's own usage line labels `9C599B32` as the card's `` and feeds the captured authentication nonces to mfkey64 to recover a Crypto1 sector key, i.e. it is a **weak-Crypto1 (attackable-PRNG) MIFARE Classic 1K** [pm3-mfkey-examples]. An LF pass over the same band would have returned nothing, since this is a 13.56 MHz HF credential, not a 125 kHz one. -That single sequence sets the whole assessment: a **MIFARE Classic 1K with a weak PRNG** is in scope for the card-only darkside bootstrap [courtois2009darkside] then nested key recovery [garcia2009pickpocketing]; a **hardened** one would instead route to hardnested [meijer2015hardnested]; had `hf search` reported **DESFire** or **NTAG**, the Crypto1 family would not apply and the assessment would pivot to its AES/configuration posture. The fork — `UID-only` vs `Crypto1` vs `DESFire AES` — is exactly what this control records, and it is decided before a single key is touched. +That single sequence sets the whole assessment: a **MIFARE Classic 1K with a weak PRNG** is in scope for the card-only darkside bootstrap [courtois2009darkside] then nested key recovery [garcia2009pickpocketing]; a **hardened** one would instead route to hardnested [meijer2015hardnested]; had `hf search` reported **DESFire** or **NTAG**, the Crypto1 family would not apply and the assessment would pivot to its AES/configuration posture. The fork, `UID-only` vs `Crypto1` vs `DESFire AES`, is exactly what this control records, and it is decided before a single key is touched. The SAK `08` / ATQA `0004` pair seen in this sample trace is the well-known MIFARE Classic 1K fingerprint, but it should always be confirmed against the specific card under test: cloned/magic Gen1a/Gen2 cards can present a non-standard SAK/ATQA even though they emulate a 1K. @@ -179,6 +179,6 @@ The SAK `08` / ATQA `0004` pair seen in this sample trace is the well-known MIFA This is an identification control; the finding it produces is "what kind of credential is this, and is it cloneable on identity alone." Remediation is therefore about not depending on a weak credential class once identified. -- **Developer (credential/chip choice):** do not deploy MIFARE Classic / Crypto1 or LF EM/HID Prox for any access decision that matters — they are identified here precisely because their family is broken [garcia2008dismantling][courtois2009darkside][meijer2015hardnested]. Specify DESFire EV2/EV3 (AES) or equivalent, and never make an access decision on UID alone (the UID is read, and cloned, at this very step). -- **Integrator (system design):** bind the access decision to cryptographic mutual authentication with diversified per-card keys, not to the card number or facility code that `lf search` / `hf search` print in the clear. Treat any system where identification alone (steps 1–2) yields everything needed to clone as already compromised. -- **Operator (monitoring/lifecycle):** inventory the credential families actually in the field (this control is the inventory tool), prioritise migrating off LF Prox and MIFARE Classic, and where migration lags, add reader-side anti-cloning/anti-relay checks and audit logging so a cloned UID does not pass silently. Frame any chip/CVE corpus as representative — check current NXP advisories, since chip families and their known weaknesses date quickly. +- **Developer (credential/chip choice):** do not deploy MIFARE Classic / Crypto1 or LF EM/HID Prox for any access decision that matters, they are identified here precisely because their family is broken [garcia2008dismantling][courtois2009darkside][meijer2015hardnested]. Specify DESFire EV2/EV3 (AES) or equivalent, and never make an access decision on UID alone (the UID is read, and cloned, at this very step). +- **Integrator (system design):** bind the access decision to cryptographic mutual authentication with diversified per-card keys, not to the card number or facility code that `lf search` / `hf search` print in the clear. Treat any system where identification alone (steps 1 to 2) yields everything needed to clone as already compromised. +- **Operator (monitoring/lifecycle):** inventory the credential families actually in the field (this control is the inventory tool), prioritise migrating off LF Prox and MIFARE Classic, and where migration lags, add reader-side anti-cloning/anti-relay checks and audit logging so a cloned UID does not pass silently. Frame any chip/CVE corpus as representative, check current NXP advisories, since chip families and their known weaknesses date quickly. diff --git a/src/content/controls/rfsam-subg-at-01.md b/src/content/controls/rfsam-subg-at-01.md index b701d9a..551ba1a 100644 --- a/src/content/controls/rfsam-subg-at-01.md +++ b/src/content/controls/rfsam-subg-at-01.md @@ -18,8 +18,8 @@ objective: >- intro: >- The code type decides the attack. A fixed-code device acts on a verbatim replay of any captured burst; a rolling-code device rejects an old code, but - is still defeated by jam-and-capture (RollJam) — withholding a valid code the - receiver never saw — or by resynchronisation replay (RollBack). This control + is still defeated by jam-and-capture (RollJam), withholding a valid code the + receiver never saw, or by resynchronisation replay (RollBack). This control verifies which of those holds, building on the demodulated frame from the capture step. prerequisites: @@ -29,7 +29,7 @@ prerequisites: software: - 'rfcat (YARD Stick One), Universal Radio Hacker (SDR replay / crafted-frame TX), Flipper Zero Sub-GHz app, or catnip (SX1262 (G)FSK)' signal: - freq: '315 MHz (NA/Asia remotes & TPMS) · 433.92 MHz (global workhorse) · 868 MHz (EU) · 915 MHz (US ISM, 902–928)' + freq: '315 MHz (NA/Asia remotes & TPMS) · 433.92 MHz (global workhorse) · 868 MHz (EU) · 915 MHz (US ISM, 902 to 928)' bandwidth: 'narrowband ISM channel; OOK/ASK bursts are a few kHz to tens of kHz wide' modulation: 'OOK/ASK (most common) or (G)FSK; PWM/Manchester/PPM bit encoding at a few hundred to a few thousand baud' skill: intermediate @@ -49,7 +49,7 @@ attacks: - opensesame - opensesame-repo impact: Opens most fixed-code garages/gates in seconds by transmitting every possible code without prior capture. - preconditions: A fixed-code receiver with a small keyspace (e.g. 8–12 DIP-switch bits) and a shift-register comparator that accepts overlapping codes. + preconditions: A fixed-code receiver with a small keyspace (e.g. 8 to 12 DIP-switch bits) and a shift-register comparator that accepts overlapping codes. summary: >- A De Bruijn sequence packs every n-bit code into a minimal overlapping bitstream, cutting a 12-bit brute force from minutes to seconds against @@ -72,8 +72,8 @@ attacks: - rollback - cve-2022-37305 - cve-2022-37418 - impact: Replaying a small set of previously captured consecutive codes resynchronises the counter so old codes become valid again — reusable indefinitely, no jamming. - preconditions: An RKE receiver that resynchronises its rolling-code counter on a short run of consecutive valid codes (RollBack research found ~70% of tested Asian-market RKE systems vulnerable; NVD records it on certain Honda through 2018 — five consecutive signals, CVE-2022-37305 — and certain Nissan, Kia and Hyundai through 2017 — two consecutive signals, CVE-2022-37418). + impact: Replaying a small set of previously captured consecutive codes resynchronises the counter so old codes become valid again, reusable indefinitely, no jamming. + preconditions: An RKE receiver that resynchronises its rolling-code counter on a short run of consecutive valid codes (RollBack research found ~70% of tested Asian-market RKE systems vulnerable; NVD records it on certain Honda through 2018, five consecutive signals, CVE-2022-37305, and certain Nissan, Kia and Hyundai through 2017, two consecutive signals, CVE-2022-37418). summary: >- Capture two-or-more consecutive codes once; replaying them in sequence rolls the receiver's counter back to a prior state, re-enabling already-used codes @@ -93,14 +93,14 @@ references: url: 'https://en.wikipedia.org/wiki/Rolling_code' type: spec - key: opensesame - title: 'OpenSesame — opening fixed-code garage doors with a De Bruijn sequence' + title: 'OpenSesame: opening fixed-code garage doors with a De Bruijn sequence' authors: S. Kamkar venue: samy.pl year: 2015 url: 'https://sa.my/opensesame/' type: blog - key: opensesame-repo - title: 'opensesame — attacks wireless garages using a Mattel toy' + title: 'opensesame: attacks wireless garages using a Mattel toy' authors: S. Kamkar venue: GitHub (samyk/opensesame) year: 2015 @@ -127,13 +127,13 @@ references: url: 'https://arxiv.org/abs/2210.11923' type: paper - key: cve-2022-37305 - title: 'CVE-2022-37305 — RollBack on certain Honda RKE receivers (five consecutive signals force resynchronisation)' + title: 'CVE-2022-37305: RollBack on certain Honda RKE receivers (five consecutive signals force resynchronisation)' venue: NVD year: 2022 url: 'https://nvd.nist.gov/vuln/detail/CVE-2022-37305' type: cve - key: cve-2022-37418 - title: 'CVE-2022-37418 — RollBack on certain Nissan, Kia and Hyundai RKE receivers (two consecutive signals force resynchronisation)' + title: 'CVE-2022-37418: RollBack on certain Nissan, Kia and Hyundai RKE receivers (two consecutive signals force resynchronisation)' venue: NVD year: 2022 url: 'https://nvd.nist.gov/vuln/detail/CVE-2022-37418' @@ -146,7 +146,7 @@ references: url: 'https://informatik.rub.de/wp-content/uploads/2022/01/crypto2008_keeloq.pdf' type: paper - key: rtl433-ev1527 - title: 'rtl_433 test corpus — EV1527 universal remote and PIR sensor sample captures (decoded Raw Codes documented in readme)' + title: 'rtl_433 test corpus: EV1527 universal remote and PIR sensor sample captures (decoded Raw Codes documented in readme)' venue: GitHub (merbanan/rtl_433_tests) year: 2024 url: 'https://github.com/merbanan/rtl_433_tests/blob/master/tests/EV1527-Universal-Remote/readme.md' @@ -168,19 +168,19 @@ lastResearched: 2026-06-14 ## Mechanism -Going active on a sub-GHz device means transmitting on its frequency to take over its function, and the single fact that decides the attack — established at the IG step — is the **code type**: fixed vs. rolling [rollingcode]. +Going active on a sub-GHz device means transmitting on its frequency to take over its function, and the single fact that decides the attack, established at the IG step, is the **code type**: fixed vs. rolling [rollingcode]. -A **fixed-code** device (a PT2262/EV1527/HT12-class OOK encoder, or a sensor) sends the same payload in the clear on every press, so there is no confidentiality to break and no counter to advance — a verbatim replay of any captured burst makes the receiver act on it [rollingcode]. Universal Radio Hacker re-transmits exactly what it captured (and can edit the bits, fix a checksum, or fuzz a field before sending) [urh]. Where the keyspace is small (8–12 DIP-switch bits) you need not even capture first: **OpenSesame** transmits a De Bruijn sequence that packs every possible code into a minimal overlapping bitstream — because a shift-register receiver also tests every shorter substring as the bits stream past — cutting a 12-bit brute force from minutes to about 8 seconds against fixed-code garages and gates [opensesame][opensesame-repo]. +A **fixed-code** device (a PT2262/EV1527/HT12-class OOK encoder, or a sensor) sends the same payload in the clear on every press, so there is no confidentiality to break and no counter to advance, a verbatim replay of any captured burst makes the receiver act on it [rollingcode]. Universal Radio Hacker re-transmits exactly what it captured (and can edit the bits, fix a checksum, or fuzz a field before sending) [urh]. Where the keyspace is small (8 to 12 DIP-switch bits) you need not even capture first: **OpenSesame** transmits a De Bruijn sequence that packs every possible code into a minimal overlapping bitstream, because a shift-register receiver also tests every shorter substring as the bits stream past, cutting a 12-bit brute force from minutes to about 8 seconds against fixed-code garages and gates [opensesame][opensesame-repo]. -A **rolling-code** device (KeeLoq / HCS301 and similar) sends a fresh value each press from a counter, so a naive replay of an old code is rejected [rollingcode]. This is replay *resistance*, not an encrypted channel you decrypt from a capture — and it is defeated without breaking the cipher. **RollJam** jams the receiver while recording the victim's first press (so the device never acts on it and the code stays unused), lets the user press again and captures that too, forwards the first code to operate the device now, and keeps the second, still-valid code to operate it later [rolljam-sdr][rolljam-rtlsdr]. **RollBack** removes the jamming entirely: replaying a short run of previously captured consecutive codes triggers a resynchronisation in many receivers, rolling the counter back to a prior state so already-used codes become valid again — captured once, reusable indefinitely [rollback]. The RollBack research reports roughly 70% of tested Asian-market RKE systems vulnerable, and NVD records it against certain Honda (through 2018, five consecutive signals) [cve-2022-37305] and certain Nissan, Kia and Hyundai (through 2017, two consecutive signals) [cve-2022-37418]; the authors additionally tested Mazda among the vulnerable makes and found Toyota not susceptible. +A **rolling-code** device (KeeLoq / HCS301 and similar) sends a fresh value each press from a counter, so a naive replay of an old code is rejected [rollingcode]. This is replay *resistance*, not an encrypted channel you decrypt from a capture, and it is defeated without breaking the cipher. **RollJam** jams the receiver while recording the victim's first press (so the device never acts on it and the code stays unused), lets the user press again and captures that too, forwards the first code to operate the device now, and keeps the second, still-valid code to operate it later [rolljam-sdr][rolljam-rtlsdr]. **RollBack** removes the jamming entirely: replaying a short run of previously captured consecutive codes triggers a resynchronisation in many receivers, rolling the counter back to a prior state so already-used codes become valid again, captured once, reusable indefinitely [rollback]. The RollBack research reports roughly 70% of tested Asian-market RKE systems vulnerable, and NVD records it against certain Honda (through 2018, five consecutive signals) [cve-2022-37305] and certain Nissan, Kia and Hyundai (through 2017, two consecutive signals) [cve-2022-37418]; the authors additionally tested Mazda among the vulnerable makes and found Toyota not susceptible. To truly *forge* the next valid rolling code offline you would need the manufacturer key programmed into the chip, which a passive RF capture never yields; recovering it requires physical side-channel access (differential power analysis), which is out of scope for this RF toolchain [keeloq-dpa]. -RollJam is Samy Kamkar's DEF CON 23 (2015) work; it is cited here via a peer-reviewed SDR re-implementation [rolljam-sdr] and a contemporaneous technical report [rolljam-rtlsdr], both of which independently describe the jam-record-replay primitive. The RollBack CVE ids above are the NVD-confirmed entries (an earlier web result that mapped RollBack to CVE-2022-37428 was wrong — that entry is an unrelated PowerDNS Recursor denial-of-service). Per-vehicle/per-device susceptibility figures are representative — check current advisories. +RollJam is Samy Kamkar's DEF CON 23 (2015) work; it is cited here via a peer-reviewed SDR re-implementation [rolljam-sdr] and a contemporaneous technical report [rolljam-rtlsdr], both of which independently describe the jam-record-replay primitive. The RollBack CVE ids above are the NVD-confirmed entries (an earlier web result that mapped RollBack to CVE-2022-37428 was wrong, that entry is an unrelated PowerDNS Recursor denial-of-service). Per-vehicle/per-device susceptibility figures are representative, check current advisories. ## Procedure -> Authorised testing only. Transmit solely on equipment you own or are explicitly authorised to test, in an RF-shielded or controlled environment. Even unlicensed ISM bands carry power and duty-cycle limits — do not jam or transmit on live third-party devices. +> Authorised testing only. Transmit solely on equipment you own or are explicitly authorised to test, in an RF-shielded or controlled environment. Even unlicensed ISM bands carry power and duty-cycle limits, do not jam or transmit on live third-party devices. 1. **Confirm the layer-1 settings and code type** carried over from capture (RFSAM-RES-15): exact carrier (315 / 433.92 / 868 / 915 MHz), OOK/ASK vs (G)FSK, baud, and fixed vs rolling. With a YARD Stick One: ```python @@ -191,44 +191,44 @@ RollJam is Samy Kamkar's DEF CON 23 (2015) work; it is cited here via a peer-rev >>> d.lowball() >>> print(d.RFrecv()[0].encode('hex')) ``` - You should see the same burst bytes each press for a fixed code, and a value that changes each press for a rolling code. The changing value is the go/no-go for steps 3–4. + You should see the same burst bytes each press for a fixed code, and a value that changes each press for a rolling code. The changing value is the go/no-go for steps 3 to 4. -2. **Fixed code — verbatim replay.** Re-send the captured burst and watch the device act. From URH's GUI use the *Generator → Send* tab on the recorded signal; from rfcat: +2. **Fixed code, verbatim replay.** Re-send the captured burst and watch the device act. From URH's GUI use the *Generator → Send* tab on the recorded signal; from rfcat: ```python >>> d.setModeTX() >>> d.RFxmit("7eXXXX...".decode('hex')) # the exact captured payload ``` Expected: the gate opens / the receiver registers the command. A Flipper Zero replays a saved fixed-code signal standalone (it refuses to save or replay rolling codes by design). -3. **Fixed code, small keyspace — De Bruijn brute force.** Where capture is impractical and the code is short, run OpenSesame's De Bruijn approach on a CC1111/CC1101 radio: +3. **Fixed code, small keyspace, De Bruijn brute force.** Where capture is impractical and the code is short, run OpenSesame's De Bruijn approach on a CC1111/CC1101 radio: ```bash - # build/flash per samyk/opensesame; transmits every 8–12-bit code as one + # build/flash per samyk/opensesame; transmits every 8 to 12-bit code as one # overlapping sequence on the target ISM frequency ``` Expected: the receiver opens within seconds rather than exhausting every code one by one [opensesame]. Authorised targets only. -4. **Rolling code — jam-and-capture (RollJam).** With one radio jamming the receiver's channel and a second recording the fob: +4. **Rolling code, jam-and-capture (RollJam).** With one radio jamming the receiver's channel and a second recording the fob: - Jam the receiver and capture the victim's **first** press (the device does not act). - Keep jamming, let the user press again, capture the **second** code. - - Stop jamming and transmit the **first** captured code — the receiver, never having advanced its counter, accepts it and operates. + - Stop jamming and transmit the **first** captured code, the receiver, never having advanced its counter, accepts it and operates. - The **second** code remains unused and valid for a later replay [rolljam-sdr][rolljam-rtlsdr]. Expected: the device operates on your replay of the first code, and the held second code still operates it afterwards. -5. **Rolling code — resynchronisation (RollBack).** Capture a run of consecutive presses, then replay them in order and observe whether the receiver rolls its counter back so already-used codes work again [rollback]. Record how many consecutive codes the target needs (the paper reports model-dependent counts). +5. **Rolling code, resynchronisation (RollBack).** Capture a run of consecutive presses, then replay them in order and observe whether the receiver rolls its counter back so already-used codes work again [rollback]. Record how many consecutive codes the target needs (the paper reports model-dependent counts). 6. **Record the finding and impact.** State the code type, which technique succeeded, what the receiver did (operated / rejected / resynchronised), and the security consequence (door/gate access, alarm sensor spoof, telemetry forgery). ## Field case -A public sample-capture set shipped with rtl_433's test corpus grounds the fixed-code half of this walkthrough. The merbanan/rtl_433_tests repository (tests/EV1527-Universal-Remote/) records a real EV1527 4-button 433.92 MHz key-fob remote captured at 250 kS/s (cu8), and its readme documents rtl_433 decoding each press to a stable Raw Code: button A → `81898a`, B → `41898a`, C → `21898a`, D → `11898a`, and A+C → `a1898a` (rtl_433 labels the decoder output "Smoke detector GS 558", id 3148, unit 10) [rtl433-ev1527]. Every press of a given button decodes byte-for-byte identically — that invariance is precisely the fixed-code signature this control looks for, and it is what makes a verbatim replay of any one captured burst sufficient to drive the receiver. A companion capture in the same corpus (tests/EV1527-PIR-SGOOWAY/) shows the SGOOWAY PR2 EV1527 PIR sensor on the same 433.92 MHz band decoding to a single fixed Raw Code `357193` (id 11148, unit 19) [rtl433-ev1527] — the same fixed-code weakness applied to an alarm sensor whose reading the panel trusts. +A public sample-capture set shipped with rtl_433's test corpus grounds the fixed-code half of this walkthrough. The merbanan/rtl_433_tests repository (tests/EV1527-Universal-Remote/) records a real EV1527 4-button 433.92 MHz key-fob remote captured at 250 kS/s (cu8), and its readme documents rtl_433 decoding each press to a stable Raw Code: button A → `81898a`, B → `41898a`, C → `21898a`, D → `11898a`, and A+C → `a1898a` (rtl_433 labels the decoder output "Smoke detector GS 558", id 3148, unit 10) [rtl433-ev1527]. Every press of a given button decodes byte-for-byte identically, that invariance is precisely the fixed-code signature this control looks for, and it is what makes a verbatim replay of any one captured burst sufficient to drive the receiver. A companion capture in the same corpus (tests/EV1527-PIR-SGOOWAY/) shows the SGOOWAY PR2 EV1527 PIR sensor on the same 433.92 MHz band decoding to a single fixed Raw Code `357193` (id 11148, unit 19) [rtl433-ev1527], the same fixed-code weakness applied to an alarm sensor whose reading the panel trusts. On an authorised bench the workflow mirrors that documented data: a single press demodulated in URH yields the short, stable EV1527 payload; re-transmitting the recorded burst through a YARD Stick One at the recovered baud operates the gate (or spoofs the sensor reading), confirming verbatim replay. -Switching to a KeeLoq rolling-code fob, two consecutive presses demodulate to two *different* payloads, and a naive replay of the older one is rejected — exactly the replay resistance a rolling code provides. The jam-and-capture path is then exercised in a shielded enclosure to validate the RollJam primitive on owned equipment. +Switching to a KeeLoq rolling-code fob, two consecutive presses demodulate to two *different* payloads, and a naive replay of the older one is rejected, exactly the replay resistance a rolling code provides. The jam-and-capture path is then exercised in a shielded enclosure to validate the RollJam primitive on owned equipment. ## Remediation -**Developer (device / chip).** Do not ship fixed-code or short-keyspace OOK remotes for anything security-relevant — they are replayable and brute-forceable [rollingcode][opensesame]. Use authenticated, rolling-code or challenge-response schemes, and harden the counter resynchronisation logic so a short run of consecutive replayed codes cannot roll the window back to a used state — the RollBack class lives precisely in over-permissive resync windows [rollback]. Treat the manufacturer key as a side-channel target and apply DPA countermeasures to the key-handling silicon [keeloq-dpa]. +**Developer (device / chip).** Do not ship fixed-code or short-keyspace OOK remotes for anything security-relevant, they are replayable and brute-forceable [rollingcode][opensesame]. Use authenticated, rolling-code or challenge-response schemes, and harden the counter resynchronisation logic so a short run of consecutive replayed codes cannot roll the window back to a used state, the RollBack class lives precisely in over-permissive resync windows [rollback]. Treat the manufacturer key as a side-channel target and apply DPA countermeasures to the key-handling silicon [keeloq-dpa]. **Integrator (system / installer).** Prefer frequency-agile or spread-spectrum links over single-frequency OOK so a jammer cannot trivially hold the receiver's channel for the jam-and-capture window [rolljam-sdr]. For safety-critical sensors, use supervised links that alarm on loss of periodic check-in and on detected jamming, so a withheld or suppressed code is itself an alert. Bind the actuation to a second factor where the consequence warrants it (a gate that also requires a presence beacon, an alarm that cross-checks a wired zone). diff --git a/src/content/controls/rfsam-subg-cr-01.md b/src/content/controls/rfsam-subg-cr-01.md index 75c6c6b..855791d 100644 --- a/src/content/controls/rfsam-subg-cr-01.md +++ b/src/content/controls/rfsam-subg-cr-01.md @@ -12,7 +12,7 @@ applicability: deferred: false objective: >- Determine whether a rolling-code sub-GHz remote can be defeated by an attacker - who captures its transmissions — through jam-and-bank replay (RollJam), + who captures its transmissions, through jam-and-bank replay (RollJam), time-agnostic resynchronisation replay (RollBack), or recovery of the device or manufacturer key from a small number of captured codes (KeeLoq / HITAG2). intro: >- @@ -24,11 +24,11 @@ intro: >- prerequisites: hardware: - 'A transmit-capable sub-GHz transceiver at the target band: YARD Stick One (CC1111), HackRF One, or a CC1101-class board (Flipper Zero / CatSniffer)' - - 'For jam-and-capture (RollJam): a second radio to jam while a first captures — e.g. two CC1101 modules, or an SDR plus a YARD Stick One' + - 'For jam-and-capture (RollJam): a second radio to jam while a first captures, e.g. two CC1101 modules, or an SDR plus a YARD Stick One' software: - 'rfcat (YARD Stick One), Universal Radio Hacker (capture/replay), rtl_433 (identify known classes); a KeeLoq/HITAG2 decoder for cipher identification' signal: - freq: '315 MHz (NA/Asia remotes) · 433.92 MHz (global workhorse) · 868 MHz (EU) · 915 MHz (US ISM, 902–928)' + freq: '315 MHz (NA/Asia remotes) · 433.92 MHz (global workhorse) · 868 MHz (EU) · 915 MHz (US ISM, 902 to 928)' bandwidth: 'Narrowband burst, a few hundred to a few thousand baud' modulation: 'OOK/ASK or (G)FSK; bits as PWM / Manchester / PPM in short repeated bursts' skill: advanced @@ -45,7 +45,7 @@ attacks: summary: >- Jams the receiver while capturing the fob's first code (the receiver never acts on it, so the code stays unused), replays an earlier captured code to - satisfy the user, and banks the fresh code for later — a captured-but-unused + satisfy the user, and banks the fresh code for later, a captured-but-unused valid code, not a broken cipher. - name: RollBack refs: @@ -126,7 +126,7 @@ references: url: 'https://www.usenix.org/conference/woot17/workshop-program/presentation/benadjila' type: paper - key: rtl433tests_hcs200 - title: 'rtl_433 test signals — Microchip HCS200 KeeLoq remote captures (tests/Microchip/HCS200/01)' + title: 'rtl_433 test signals: Microchip HCS200 KeeLoq remote captures (tests/Microchip/HCS200/01)' authors: merbanan and contributors venue: merbanan/rtl_433_tests year: 2020 @@ -148,11 +148,11 @@ lastResearched: 2026-06-14 ## Mechanism -A rolling-code remote sends a fresh value on every press: a synchronisation counter is incremented and the message is transformed (encrypted, in the KeeLoq case) so that the receiver, which tracks the expected counter within a window, rejects any code it has already seen. This defeats a naive capture-and-replay — the captured code is stale by the time it is re-sent. It does **not** provide confidentiality you can decrypt from a passive capture, and the fixed serial number in the frame is still sent in the clear (RFSAM-RES-15). Three documented attack families break the protection without any general offline "cracker". +A rolling-code remote sends a fresh value on every press: a synchronisation counter is incremented and the message is transformed (encrypted, in the KeeLoq case) so that the receiver, which tracks the expected counter within a window, rejects any code it has already seen. This defeats a naive capture-and-replay, the captured code is stale by the time it is re-sent. It does **not** provide confidentiality you can decrypt from a passive capture, and the fixed serial number in the frame is still sent in the clear (RFSAM-RES-15). Three documented attack families break the protection without any general offline "cracker". **Jam-and-bank (RollJam).** The receiver only consumes a code it actually hears. RollJam jams the receiver's band while capturing the owner's press, so that code is never consumed and stays valid; when the owner presses again, the attacker captures the second code, replays the *first* (now-valid) one to operate the device so the owner notices nothing, and banks the second for later use [kamkar2015rolljam]. The bypass is a captured-but-unused valid code, not a cipher break. Samy Kamkar demonstrated this at DEF CON 23 against remotes from multiple car and garage-door makers using roughly $32 of hardware (a microcontroller and two CC1101 433 MHz transceivers) [kamkar2015rolljam]. -**Time-agnostic resync replay (RollBack).** Many RKE receivers accept a short *ordered sequence* of previously-valid codes as a counter-resynchronisation gesture. RollBack shows that re-transmitting a few previously-captured codes consecutively pushes the receiver's counter back into a state where old captures are accepted again — with no jamming, from a single capture session, repeatable at any future time [csikor2022rollback]. The authors report that the number of codes that triggers the resync varies (a sequence on the order of a few) and that a substantial fraction of tested vehicles were affected [csikor2022rollback]. +**Time-agnostic resync replay (RollBack).** Many RKE receivers accept a short *ordered sequence* of previously-valid codes as a counter-resynchronisation gesture. RollBack shows that re-transmitting a few previously-captured codes consecutively pushes the receiver's counter back into a state where old captures are accepted again, with no jamming, from a single capture session, repeatable at any future time [csikor2022rollback]. The authors report that the number of codes that triggers the resync varies (a sequence on the order of a few) and that a substantial fraction of tested vehicles were affected [csikor2022rollback]. **Key recovery / cloning (KeeLoq, HITAG2).** Where the rolling code is built on a broken cipher, the keys can be recovered. KeeLoq code-hopping (HCS200/300/301) has been cryptanalysed: a slide / meet-in-the-middle attack recovers the device key from a set of known plaintext codes [indesteege2008keeloq], and a differential-power-analysis attack against a receiver recovers the shared *manufacturer* key, after which a remote can be cloned by eavesdropping at most two over-the-air codes [eisenbarth2008keeloq]. HITAG2, used in some vehicle RKE systems, is likewise broken: a few captured RKE radio packets (reported four to eight) recover the key, though implementations with specific countermeasures resisted the attack [benadjila2017hitag2]. This control assesses which of these apply to the target. @@ -170,13 +170,13 @@ All transmit, jam and replay steps are active radio attacks. Perform them **only 2. **Capture two consecutive presses and confirm the counter advances.** Record raw bursts in Universal Radio Hacker (or via rfcat), align them, and diff: ```bash - # YARD Stick One, rfcat shell — receive bursts at the recovered settings + # YARD Stick One, rfcat shell, receive bursts at the recovered settings rfcat -r # in the shell: d.setFreq(433920000); d.setMdmModulation(MOD_ASK_OOK); d.setMdmDRate(2400) print(d.RFrecv()) ``` - Two presses should differ in the rolling field while the serial prefix stays constant — this confirms a genuine rolling code and locates the counter bytes. + Two presses should differ in the rolling field while the serial prefix stays constant, this confirms a genuine rolling code and locates the counter bytes. 3. **Identify the cipher.** From the teardown / FCC ID (IG step) determine the encoder: a KeeLoq HCS200/300/301 (code-hopping), a HITAG2 RKE controller, or a vendor scheme. The chip decides whether key recovery [eisenbarth2008keeloq, indesteege2008keeloq, benadjila2017hitag2] is even applicable, versus replay-only. @@ -199,17 +199,17 @@ All transmit, jam and replay steps are active radio attacks. Perform them **only 6. **Assess key-recovery feasibility.** For KeeLoq, capture the known-plaintext codes the cryptanalysis needs and document whether offline key recovery is in scope [indesteege2008keeloq]; the practical clone additionally needs the manufacturer key, recovered by side channel from a receiver, then at most two eavesdropped codes [eisenbarth2008keeloq]. For HITAG2 RKE, capture the reported four-to-eight packets and check the implementation against the known countermeasures [benadjila2017hitag2]. -7. **Record defences.** Note any jamming detection, tight/non-resettable counter windows, time-bounded acceptance, bidirectional challenge-response, or migration off KeeLoq/HITAG2 — each closes one or more of the families above. +7. **Record defences.** Note any jamming detection, tight/non-resettable counter windows, time-bounded acceptance, bidirectional challenge-response, or migration off KeeLoq/HITAG2, each closes one or more of the families above. ## Field case -> [!NOTE] The identify-and-confirm steps below (procedure steps 1–3) are grounded in a documented public capture corpus, not a first-party measured attack. The RollJam / RollBack / key-recovery sub-steps remain a representative checklist — they must be run against your own authorised target. +> [!NOTE] The identify-and-confirm steps below (procedure steps 1 to 3) are grounded in a documented public capture corpus, not a first-party measured attack. The RollJam / RollBack / key-recovery sub-steps remain a representative checklist, they must be run against your own authorised target. -As a public reference for the identify-and-confirm steps, the rtl_433 test corpus ships Microchip KeeLoq **HCS200** captures at **433.92 MHz, OOK/PWM**, sampled at 250 ksps, with a documented rtl_433 decode (merbanan/rtl_433_tests, `tests/Microchip/HCS200/01`) [rtl433tests_hcs200]. The README decoder records the symbol timing as short pulse ~370 µs, long pulse ~772 µs, gap ~4000 µs and inter-frame repeat ~14000 µs, behind a 12-pulse preamble (`0xfff`) [rtl433tests_hcs200] — the OOK/PWM equivalent of the **measured baud** the procedure asks for. +As a public reference for the identify-and-confirm steps, the rtl_433 test corpus ships Microchip KeeLoq **HCS200** captures at **433.92 MHz, OOK/PWM**, sampled at 250 ksps, with a documented rtl_433 decode (merbanan/rtl_433_tests, `tests/Microchip/HCS200/01`) [rtl433tests_hcs200]. The README decoder records the symbol timing as short pulse ~370 µs, long pulse ~772 µs, gap ~4000 µs and inter-frame repeat ~14000 µs, behind a 12-pulse preamble (`0xfff`) [rtl433tests_hcs200], the OOK/PWM equivalent of the **measured baud** the procedure asks for. -Across three consecutive button-1 presses (`g001`/`g002`/`g003`), the decoded frame carries a constant **serial id `00D0921`** (`button: 1`) while the 32-bit `encrypted` (rolling) field changes every press — `528F2DB8` → `3CA7B9F4` → `D087C973` [rtl433tests_hcs200]. The fixed serial alongside a changing hopping field is exactly the rolling-code signature procedure steps 1–2 look for. rtl_433's own model string identifies the **encoder as a Microchip KeeLoq HCS200** and therefore the **cipher as KeeLoq** (step 3); the companion `tests/keeloq/01` capture corroborates the pattern, with a constant static tail (`…b3 52 e8`), a changing leading 32-bit rolling field, and the button byte varying (`02` vs `04`) between presses [rtl433tests_hcs200]. +Across three consecutive button-1 presses (`g001`/`g002`/`g003`), the decoded frame carries a constant **serial id `00D0921`** (`button: 1`) while the 32-bit `encrypted` (rolling) field changes every press, `528F2DB8` → `3CA7B9F4` → `D087C973` [rtl433tests_hcs200]. The fixed serial alongside a changing hopping field is exactly the rolling-code signature procedure steps 1 to 2 look for. rtl_433's own model string identifies the **encoder as a Microchip KeeLoq HCS200** and therefore the **cipher as KeeLoq** (step 3); the companion `tests/keeloq/01` capture corroborates the pattern, with a constant static tail (`…b3 52 e8`), a changing leading 32-bit rolling field, and the button byte varying (`02` vs `04`) between presses [rtl433tests_hcs200]. -The active-attack sub-steps below are a representative checklist against your own authorised remote — they are **not** demonstrated by the public corpus, which is a passive decode only: +The active-attack sub-steps below are a representative checklist against your own authorised remote, they are **not** demonstrated by the public corpus, which is a passive decode only: - **RollJam:** with a second YARD Stick One jamming the receiver while the first captures, the owner's press is denied and a banked code later opens the gate: `[FILL: observed yes/no, banked-code latency]`. Jamming detection present: `[FILL: yes/no]`. - **RollBack:** replaying `[FILL: N]` consecutive captured codes in order, then an earlier code: accepted = `[FILL: yes/no]`, resync depth = `[FILL: N]`. @@ -219,8 +219,8 @@ The auditor's verdict is the trio: jam-and-bank feasible, resync depth, and whet ## Remediation -**Developer (silicon / firmware).** Do not build new designs on KeeLoq code-hopping or HITAG2 for RKE — both are cryptographically broken [eisenbarth2008keeloq, indesteege2008keeloq, benadjila2017hitag2]. Use an authenticated, ideally **bidirectional challenge-response** scheme with a modern cipher and per-device keys, so a one-way captured code cannot be banked or resynced. Constrain the counter resynchronisation logic: require a tight, monotonic, non-resettable window and reject the ordered-replay resync gesture that RollBack abuses [csikor2022rollback]. +**Developer (silicon / firmware).** Do not build new designs on KeeLoq code-hopping or HITAG2 for RKE, both are cryptographically broken [eisenbarth2008keeloq, indesteege2008keeloq, benadjila2017hitag2]. Use an authenticated, ideally **bidirectional challenge-response** scheme with a modern cipher and per-device keys, so a one-way captured code cannot be banked or resynced. Constrain the counter resynchronisation logic: require a tight, monotonic, non-resettable window and reject the ordered-replay resync gesture that RollBack abuses [csikor2022rollback]. **Integrator (product).** Implement jamming detection on the receiver so a RollJam-style denied press is observable rather than silent [kamkar2015rolljam]. Add time-bounding to code acceptance so a code captured long ago cannot be presented later, defeating the time-agnostic RollBack replay [csikor2022rollback]. Protect receivers against side-channel manufacturer-key extraction (the step that turns KeeLoq from a per-device problem into a fleet-wide one) [eisenbarth2008keeloq]. -**Operator (deployment).** Treat any rolling-code remote on a broken cipher as replay- and clone-exposed: for high-value access (vehicles, gates, alarms) layer a second factor or a separate authenticated channel rather than relying on the fob alone, and prefer products that document a modern authenticated RKE scheme over legacy KeeLoq/HITAG2 fobs. Frame any specific product/CVE corpus as representative and check current advisories — these schemes and their countermeasures date quickly. +**Operator (deployment).** Treat any rolling-code remote on a broken cipher as replay- and clone-exposed: for high-value access (vehicles, gates, alarms) layer a second factor or a separate authenticated channel rather than relying on the fob alone, and prefer products that document a modern authenticated RKE scheme over legacy KeeLoq/HITAG2 fobs. Frame any specific product/CVE corpus as representative and check current advisories, these schemes and their countermeasures date quickly. diff --git a/src/content/controls/rfsam-subg-ll-01.md b/src/content/controls/rfsam-subg-ll-01.md index e7581f1..2922024 100644 --- a/src/content/controls/rfsam-subg-ll-01.md +++ b/src/content/controls/rfsam-subg-ll-01.md @@ -14,13 +14,13 @@ applicability: deferred: false objective: >- Determine whether a Sub-GHz device's frame structure and addressing can be - recovered from captured bursts — the preamble/sync word, the device address/ID, - the command/state fields, any counter, and the checksum/CRC — and whether that + recovered from captured bursts, the preamble/sync word, the device address/ID, + the command/state fields, any counter, and the checksum/CRC, and whether that address acts as authentication or merely as identification. intro: >- At the link layer a Sub-GHz burst is just an ID plus a few state bytes and a checksum. This control recovers that frame format and, critically, the device - address — the field a receiver uses to decide whose message it is. On most ISM + address, the field a receiver uses to decide whose message it is. On most ISM devices that address is a fixed, in-the-clear identifier, so recovering the frame is equivalent to recovering everything the receiver trusts. prerequisites: @@ -40,7 +40,7 @@ attacks: - rtl433dataformat impact: >- A receiver that acts on any frame carrying a known device ID will act on a - replayed or forged frame bearing that same ID — the recovered address is + replayed or forged frame bearing that same ID, the recovered address is sufficient to be trusted. preconditions: The device address is a fixed, in-the-clear field with no rolling counter, MAC, or signature over the frame. summary: >- @@ -53,7 +53,7 @@ attacks: - opensesame - hackaday-opensesame impact: >- - Where the address is set by 8–12 DIP switches the keyspace is 2^8–2^12, so + Where the address is set by 8 to 12 DIP switches the keyspace is 2^8 to 2^12, so the address can be enumerated rather than captured; a De Bruijn sequence collapses the brute-force time to seconds. preconditions: Fixed-code receiver with a short DIP-switch address space and no rate limiting; active transmission (assessed under RFSAM-SUBG-AT-01). @@ -63,7 +63,7 @@ attacks: layer, but recovering the frame is what reveals the keyspace. references: - key: rtl433 - title: 'rtl_433 — decode radio transmissions from devices on the ISM bands' + title: 'rtl_433: decode radio transmissions from devices on the ISM bands' authors: B. Larsson (merbanan) and contributors venue: GitHub year: 2026 @@ -76,7 +76,7 @@ references: url: 'https://triq.org/rtl_433/DATA_FORMAT.html' type: spec - key: rtl433tests-generic-remote - title: 'rtl_433_tests — generic_remote/01 sample capture (SC2260 fixed-code OOK remote): expected JSON decode and Readme.txt' + title: 'rtl_433_tests: generic_remote/01 sample capture (SC2260 fixed-code OOK remote): expected JSON decode and Readme.txt' authors: B. Larsson (merbanan) and contributors venue: GitHub year: 2026 @@ -104,13 +104,13 @@ references: url: 'https://archive.org/details/ossmann-rapid-radio-reversing-toorcon-2015' type: talk - key: ev1527 - title: 'EV1527 OTP encoder — datasheet, pinout and frame (preamble + 20-bit address + 4-bit data)' + title: 'EV1527 OTP encoder: datasheet, pinout and frame (preamble + 20-bit address + 4-bit data)' venue: components101 year: 2021 url: 'https://components101.com/ics/ev1527-encoder-ic-pinout-datasheet-equivalent-circuit-specs' type: standard - key: opensesame - title: 'OpenSesame — open most fixed-code garages and gates in seconds using a Mattel toy' + title: 'OpenSesame: open most fixed-code garages and gates in seconds using a Mattel toy' authors: S. Kamkar venue: GitHub year: 2015 @@ -137,23 +137,23 @@ lastResearched: 2026-06-14 --- ## Mechanism -A Sub-GHz frame is small: a preamble/sync, a device address (ID), a few command or sensor bytes, and usually a checksum, sent in short bursts that often repeat several times per event for reliability. The link-layer question this control answers is **whose frame is it, and what does the receiver check** — which means recovering the frame structure and, above all, the address field. +A Sub-GHz frame is small: a preamble/sync, a device address (ID), a few command or sensor bytes, and usually a checksum, sent in short bursts that often repeat several times per event for reliability. The link-layer question this control answers is **whose frame is it, and what does the receiver check**, which means recovering the frame structure and, above all, the address field. -For the hundreds of recognised device classes, `rtl_433` demodulates and decodes the burst to named JSON fields in one pass, exposing the model, the device `id`, and the payload [rtl433]. The project's data-format documentation is explicit that the `id` field is "Device identification. Used to differentiate between devices of same model," and that depending on the device it "may be a non-volatile value programmed into the device, a volatile value that changes at each power on (or battery change), or a value configurable by user e.g. by switch or jumpers" [rtl433dataformat]. That single sentence is the crux of the layer: the address is *identification*, not *authentication* — the receiver uses it to decide a frame is "for me," but nothing in the frame proves the frame was produced by the legitimate transmitter. +For the hundreds of recognised device classes, `rtl_433` demodulates and decodes the burst to named JSON fields in one pass, exposing the model, the device `id`, and the payload [rtl433]. The project's data-format documentation is explicit that the `id` field is "Device identification. Used to differentiate between devices of same model," and that depending on the device it "may be a non-volatile value programmed into the device, a volatile value that changes at each power on (or battery change), or a value configurable by user e.g. by switch or jumpers" [rtl433dataformat]. That single sentence is the crux of the layer: the address is *identification*, not *authentication*, the receiver uses it to decide a frame is "for me," but nothing in the frame proves the frame was produced by the legitimate transmitter. -For an unrecognised or proprietary frame, Universal Radio Hacker is the reversing workbench: load the demodulated bitstream, then diff several captures of the same and different events to label the fields — the bytes that never change across presses are the address/preamble, the bytes that change with the button are the command, and a multi-byte field that increments every press is a rolling counter [urh]. Capturing two presses and seeing what changes is the fastest route from raw bits to a labelled frame. (URH's repository is archived but remains the de-facto unknown-signal tool [urh].) +For an unrecognised or proprietary frame, Universal Radio Hacker is the reversing workbench: load the demodulated bitstream, then diff several captures of the same and different events to label the fields, the bytes that never change across presses are the address/preamble, the bytes that change with the button are the command, and a multi-byte field that increments every press is a rolling counter [urh]. Capturing two presses and seeing what changes is the fastest route from raw bits to a labelled frame. (URH's repository is archived but remains the de-facto unknown-signal tool [urh].) -The canonical example of a fixed address is the EV1527/PT2262 OOK encoder family: the output frame is a preamble followed by a 20-bit address and 4 data bits, with the address one-time-programmed (or set by DIP switches on older PT2262/EV1527 boards) [ev1527]. Recovering this frame tells you immediately whether you face a fixed address (the same address every burst — replayable, addressed under RFSAM-SUBG-AT-01) or a rolling counter (assessed under RFSAM-SUBG-CR-01). Where the address is a short DIP-switch field — for example the 12 binary DIP switches of many older fixed-code garage remotes, a 2^12 = 4096 keyspace — the recovered frame also reveals that the address space is small enough to enumerate rather than capture; OpenSesame demonstrated reducing that brute force to seconds with a De Bruijn sequence [opensesame] [hackaday-opensesame] (the active transmission belongs to the Attack layer). The discover-demodulate-reverse workflow this control sits in was formalised by Ossmann as "Rapid Radio Reversing": use a wideband SDR to characterise the signal, then a CC1101-class radio to receive and work it [ossmann2015] [ossmann2015archive] (RFSAM-RES-15). +The canonical example of a fixed address is the EV1527/PT2262 OOK encoder family: the output frame is a preamble followed by a 20-bit address and 4 data bits, with the address one-time-programmed (or set by DIP switches on older PT2262/EV1527 boards) [ev1527]. Recovering this frame tells you immediately whether you face a fixed address (the same address every burst, replayable, addressed under RFSAM-SUBG-AT-01) or a rolling counter (assessed under RFSAM-SUBG-CR-01). Where the address is a short DIP-switch field, for example the 12 binary DIP switches of many older fixed-code garage remotes, a 2^12 = 4096 keyspace, the recovered frame also reveals that the address space is small enough to enumerate rather than capture; OpenSesame demonstrated reducing that brute force to seconds with a De Bruijn sequence [opensesame] [hackaday-opensesame] (the active transmission belongs to the Attack layer). The discover-demodulate-reverse workflow this control sits in was formalised by Ossmann as "Rapid Radio Reversing": use a wideband SDR to characterise the signal, then a CC1101-class radio to receive and work it [ossmann2015] [ossmann2015archive] (RFSAM-RES-15). ## Procedure -> Receive-only throughout — this control recovers structure from captured bursts and does not transmit. Capture only devices you own or are explicitly authorised to assess. +> Receive-only throughout, this control recovers structure from captured bursts and does not transmit. Capture only devices you own or are explicitly authorised to assess. 1. **Try the known-device path first.** Point `rtl_433` at the target band and trigger the device; if it is a recognised class it decodes straight to named fields including the address: ```bash rtl_433 -f 433.92M -F json ``` - Expected: one JSON line per burst, e.g. `{"model":"...","id":12345,"channel":1,...}`. The `id` is the recovered link-layer address; `model` names the protocol/field layout for free [rtl433] [rtl433dataformat]. If nothing decodes, energy is present but the class is unknown — go to step 2. + Expected: one JSON line per burst, e.g. `{"model":"...","id":12345,"channel":1...}`. The `id` is the recovered link-layer address; `model` names the protocol/field layout for free [rtl433] [rtl433dataformat]. If nothing decodes, energy is present but the class is unknown, go to step 2. 2. **Record raw bursts for an unknown frame.** Capture I/Q at the carrier and bandwidth found at the Spectrum/PHY steps (RFSAM-RES-15), triggering the device several times: ```bash @@ -175,11 +175,11 @@ The canonical example of a fixed address is the EV1527/PT2262 OOK encoder family ``` Expected: the same address/command bytes you labelled in step 3, confirming the frame map. A CC1101 Flipper Zero's Sub-GHz "Read RAW" captures the same burst standalone for field work [ossmann2015]. -5. **Classify the address.** Record whether the recovered address is fixed (same every burst — identification only), DIP-switch-set (small enumerable keyspace), volatile (changes at power-on), or accompanied by a rolling counter / MAC. This classification is the control's finding. +5. **Classify the address.** Record whether the recovered address is fixed (same every burst, identification only), DIP-switch-set (small enumerable keyspace), volatile (changes at power-on), or accompanied by a rolling counter / MAC. This classification is the control's finding. ## Field case -A documented public example makes the fixed-address pattern concrete. A sample capture set shipped with the rtl_433 test corpus (merbanan/rtl_433_tests, `tests/generic_remote/01/` — an SC2260 fixed-code OOK remote of the PT2262/EV1527 family) decodes via `rtl_433` to the project's recorded expected JSON [rtl433tests-generic-remote]: +A documented public example makes the fixed-address pattern concrete. A sample capture set shipped with the rtl_433 test corpus (merbanan/rtl_433_tests, `tests/generic_remote/01/`, an SC2260 fixed-code OOK remote of the PT2262/EV1527 family) decodes via `rtl_433` to the project's recorded expected JSON [rtl433tests-generic-remote]: ```bash rtl_433 -f 433.92M -F json @@ -192,10 +192,10 @@ Pressing "arm" yields a line naming the device and a stable identifier; pressing {"model":"Generic-Remote","id":5069,"cmd":12} ``` -The `id` is identical (`5069` = `0x13CD`) across both captures while `cmd` changes with the button (`192` for "arm", `12` for "disarm"), which is exactly the fixed-address / variable-command pattern — the `id` is the device address, not the command [rtl433dataformat] [rtl433tests-generic-remote]. The repo's `Readme.txt` documents the device and the per-file button mapping and reports the decode "ID 16bit = 0x13CD" (= 5069) [rtl433tests-generic-remote]. Loading the captures into URH and diffing them, the leading 16-bit field is constant (preamble + address), the command field changes only with the button, and no field increments between presses — the signature of a **fixed code: identification only, no counter, no checksum over a secret** [urh] [ev1527]. The security finding then writes itself: the receiver acts on any frame carrying that address, so the recovered frame is everything it trusts. Because this class's address is often a short DIP-switch or OTP field, the same recovery that reads the address also bounds the keyspace — the kind of small fixed-code space OpenSesame enumerated in seconds [opensesame] [hackaday-opensesame] — though the active replay and brute force themselves are assessed under RFSAM-SUBG-AT-01. +The `id` is identical (`5069` = `0x13CD`) across both captures while `cmd` changes with the button (`192` for "arm", `12` for "disarm"), which is exactly the fixed-address / variable-command pattern, the `id` is the device address, not the command [rtl433dataformat] [rtl433tests-generic-remote]. The repo's `Readme.txt` documents the device and the per-file button mapping and reports the decode "ID 16bit = 0x13CD" (= 5069) [rtl433tests-generic-remote]. Loading the captures into URH and diffing them, the leading 16-bit field is constant (preamble + address), the command field changes only with the button, and no field increments between presses, the signature of a **fixed code: identification only, no counter, no checksum over a secret** [urh] [ev1527]. The security finding then writes itself: the receiver acts on any frame carrying that address, so the recovered frame is everything it trusts. Because this class's address is often a short DIP-switch or OTP field, the same recovery that reads the address also bounds the keyspace, the kind of small fixed-code space OpenSesame enumerated in seconds [opensesame] [hackaday-opensesame], though the active replay and brute force themselves are assessed under RFSAM-SUBG-AT-01. ## Remediation -- **Developer (device/firmware):** Do not let the device address stand in for authentication. Add a per-message authenticator — a rolling counter at minimum (defeats naive replay; see RFSAM-SUBG-CR-01) and ideally a MAC/signature over the whole frame keyed to a per-device secret — so a recovered address cannot be reused or forged. Avoid encoders whose entire "security" is a fixed OTP/DIP-switch address in clear OOK [ev1527]. +- **Developer (device/firmware):** Do not let the device address stand in for authentication. Add a per-message authenticator, a rolling counter at minimum (defeats naive replay; see RFSAM-SUBG-CR-01) and ideally a MAC/signature over the whole frame keyed to a per-device secret, so a recovered address cannot be reused or forged. Avoid encoders whose entire "security" is a fixed OTP/DIP-switch address in clear OOK [ev1527]. - **Integrator (product/installer):** Choose modules with adequately sized, factory-randomised addresses rather than installer-set DIP switches, and prefer rolling-/authenticated-code receivers over fixed-code ones for anything that grants physical access [opensesame]. Treat the printed FCC ID and any default address as known to an attacker. - **Operator (deployment):** Assume any fixed-code remote, sensor or fob transmitting in the clear is identifiable and replayable once its frame is recovered; reserve such devices for non-safety functions and add an independent supervision/authorisation layer (rate limiting, second factor, alarm supervision) where they gate access. Identification is not authentication. diff --git a/src/content/controls/rfsam-subg-phy-01.md b/src/content/controls/rfsam-subg-phy-01.md index 82f1ea0..5638bf2 100644 --- a/src/content/controls/rfsam-subg-phy-01.md +++ b/src/content/controls/rfsam-subg-phy-01.md @@ -14,13 +14,13 @@ applicability: deferred: false objective: >- Verify whether a captured Sub-GHz burst can be demodulated to a clean - bitstream and framed into symbols — recovering the modulation, bit rate and - line coding well enough to deliver bits to the link layer — without any key + bitstream and framed into symbols, recovering the modulation, bit rate and + line coding well enough to deliver bits to the link layer, without any key material. intro: >- Most ISM-band devices transmit narrowband OOK/ASK or (G)FSK with no spreading or scrambling, so a captured burst demodulates to bits with SDR tooling plus a - CC1101-class radio. This control turns the waveform into framed symbols — the + CC1101-class radio. This control turns the waveform into framed symbols, the prerequisite that every downstream replay, forgery or analysis depends on. prerequisites: hardware: @@ -32,7 +32,7 @@ prerequisites: - 'rfcat (drive a YARD Stick One at recovered layer-1 settings)' signal: freq: '315 / 433.92 / 868 / 915 MHz regional ISM (sub-1.7 GHz)' - bandwidth: 'Narrowband — a few kHz to low tens of kHz; sample rate must cover the burst bandwidth' + bandwidth: 'Narrowband, a few kHz to low tens of kHz; sample rate must cover the burst bandwidth' modulation: 'OOK/ASK or (G)FSK; line coding usually PWM, PPM, Manchester or raw NRZ at a few hundred to a few thousand baud' skill: intermediate attacks: @@ -48,7 +48,7 @@ attacks: unscrambled OOK/ASK or (G)FSK, as nearly all sub-GHz ISM devices are. summary: >- Because the waveform carries the bits in the clear, demodulating and framing - it is a tooling exercise, not a cryptographic one — the PHY layer offers no + it is a tooling exercise, not a cryptographic one, the PHY layer offers no barrier on its own. - name: Automatic demodulation-parameter detection refs: @@ -63,7 +63,7 @@ attacks: recording, lowering the skill needed to frame an unknown burst. references: - key: rtl433primer - title: 'rtl_433 — Primer on ISM-band signal modulation and pulse coding (OOK/ASK, FSK, PWM/PPM/Manchester/NRZ)' + title: 'rtl_433: Primer on ISM-band signal modulation and pulse coding (OOK/ASK, FSK, PWM/PPM/Manchester/NRZ)' authors: 'B. Larsson (merbanan) et al.' venue: rtl_433 project documentation year: 2024 @@ -91,21 +91,21 @@ references: url: 'https://www.usenix.org/conference/woot19/presentation/pohl' type: paper - key: urhrepo - title: 'Universal Radio Hacker (URH) — source repository' + title: 'Universal Radio Hacker (URH): source repository' authors: 'J. Pohl (jopohl)' venue: GitHub year: 2024 url: 'https://github.com/jopohl/urh' type: tool - key: rtl433repo - title: 'rtl_433 — decoder for ISM-band radio transmissions' + title: 'rtl_433: decoder for ISM-band radio transmissions' authors: 'B. Larsson (merbanan) et al.' venue: GitHub year: 2024 url: 'https://github.com/merbanan/rtl_433' type: tool - key: rtl433ev1527 - title: 'rtl_433 — Generic Remote SC226x EV1527 decoder (generic_remote.c) and EV1527 flex spec / sample corpus' + title: 'rtl_433: Generic Remote SC226x EV1527 decoder (generic_remote.c) and EV1527 flex spec / sample corpus' authors: 'B. Larsson (merbanan) et al.' venue: 'merbanan/rtl_433 + merbanan/rtl_433_tests' year: 2024 @@ -127,17 +127,17 @@ lastResearched: 2026-06-14 --- ## Mechanism -Sub-GHz ISM devices are built for cost, not stealth: nearly all of them transmit narrowband **OOK/ASK** (the carrier blinks the bits on and off) or **(G)FSK** (the carrier shifts between two tones), with no spread-spectrum and no scrambling [rtl433primer]. That makes the physical layer a pure signal-processing problem — there is no key, no de-spreading, and no channel hopping to defeat before the bits appear. Demodulation recovers the symbol stream; framing then resolves the **line coding** — typically PWM, PPM, Manchester or raw NRZ at a few hundred to a few thousand baud — into bits [rtl433primer]. +Sub-GHz ISM devices are built for cost, not stealth: nearly all of them transmit narrowband **OOK/ASK** (the carrier blinks the bits on and off) or **(G)FSK** (the carrier shifts between two tones), with no spread-spectrum and no scrambling [rtl433primer]. That makes the physical layer a pure signal-processing problem, there is no key, no de-spreading, and no channel hopping to defeat before the bits appear. Demodulation recovers the symbol stream; framing then resolves the **line coding**, typically PWM, PPM, Manchester or raw NRZ at a few hundred to a few thousand baud, into bits [rtl433primer]. -Two demodulation paths exist, and they are equivalent at this layer. A **software path** loads an I/Q recording from an SDR and slices it: rtl_433 runs a pulse demodulator and, with `-A`, reports the measured pulse width, gap width and period so you can read the coding by eye, while `-X` lets you write a flex decoder for an unrecognised device [rtl433primer]. A **hardware path** programs a CC1101/CC1111-class transceiver (driven by rfcat) to the recovered carrier, modulation and baud, letting the radio chip itself do the demodulation — the hybrid SDR-plus-dedicated-radio workflow Ossmann set out as "rapid radio reversing" [ossmann2015rrr]. Universal Radio Hacker sits in the middle: it visualises the burst, **auto-detects the modulation and bit length** directly from the I/Q, and extracts the bitstream [pohl2018urh][urhrepo]. That auto-detection — estimating all the demodulation parameters from the recording so an analyst can skip the physical layer — is the subject of Pohl and Noack's follow-on work [pohl2019autopre]. +Two demodulation paths exist, and they are equivalent at this layer. A **software path** loads an I/Q recording from an SDR and slices it: rtl_433 runs a pulse demodulator and, with `-A`, reports the measured pulse width, gap width and period so you can read the coding by eye, while `-X` lets you write a flex decoder for an unrecognised device [rtl433primer]. A **hardware path** programs a CC1101/CC1111-class transceiver (driven by rfcat) to the recovered carrier, modulation and baud, letting the radio chip itself do the demodulation, the hybrid SDR-plus-dedicated-radio workflow Ossmann set out as "rapid radio reversing" [ossmann2015rrr]. Universal Radio Hacker sits in the middle: it visualises the burst, **auto-detects the modulation and bit length** directly from the I/Q, and extracts the bitstream [pohl2018urh][urhrepo]. That auto-detection, estimating all the demodulation parameters from the recording so an analyst can skip the physical layer, is the subject of Pohl and Noack's follow-on work [pohl2019autopre]. -The security relevance at PHY is exactly this absence of a barrier. Because the bits travel in the clear, framing the burst is a tooling exercise rather than a cryptographic one [ossmann2015rrr][rtl433primer]; the recovered bitstream is what every downstream control — capture/replay, rolling-vs-fixed determination, forgery — consumes. This control verifies only that the bits can be recovered cleanly; it does not yet replay or forge them. +The security relevance at PHY is exactly this absence of a barrier. Because the bits travel in the clear, framing the burst is a tooling exercise rather than a cryptographic one [ossmann2015rrr][rtl433primer]; the recovered bitstream is what every downstream control, capture/replay, rolling-vs-fixed determination, forgery, consumes. This control verifies only that the bits can be recovered cleanly; it does not yet replay or forge them. -The applicability list and the bit-rate range ("a few hundred to a few thousand baud") are the representative envelope for the band — the modulation and line-coding families and the few-hundred-to-few-thousand-baud range are the general behaviour documented for ISM-band devices [rtl433primer], not a guarantee for any one target, which must be measured per device. +The applicability list and the bit-rate range ("a few hundred to a few thousand baud") are the representative envelope for the band, the modulation and line-coding families and the few-hundred-to-few-thousand-baud range are the general behaviour documented for ISM-band devices [rtl433primer], not a guarantee for any one target, which must be measured per device. ## Procedure -All steps below are passive receive-and-demodulate. They involve no transmission and so need no special authorisation, but any later replay/forgery step does — perform those only on equipment you own or are explicitly authorised to test. +All steps below are passive receive-and-demodulate. They involve no transmission and so need no special authorisation, but any later replay/forgery step does, perform those only on equipment you own or are explicitly authorised to test. 1. **Capture the burst as I/Q**, centred on the carrier found at the Spectrum step, at a sample rate that comfortably covers the burst bandwidth. With an RTL-SDR or HackRF: ```bash @@ -149,7 +149,7 @@ All steps below are passive receive-and-demodulate. They involve no transmission ```bash rtl_433 -f 433.92M -A ``` - Expected: for a recognised device, a JSON line naming it; for an unknown one, the analyzer prints measured **pulse width, gap width and pulse period** and a guess at the coding (OOK_PWM / OOK_PPM / OOK_MC / FSK). Read those numbers — they are the bit rate and line coding [rtl433primer]. + Expected: for a recognised device, a JSON line naming it; for an unknown one, the analyzer prints measured **pulse width, gap width and pulse period** and a guess at the coding (OOK_PWM / OOK_PPM / OOK_MC / FSK). Read those numbers, they are the bit rate and line coding [rtl433primer]. 3. **Demodulate and frame in Universal Radio Hacker** when rtl_433 has no decoder. Load the recording and let URH auto-detect: ```bash @@ -157,7 +157,7 @@ All steps below are passive receive-and-demodulate. They involve no transmission ``` Expected: URH labels the **modulation** (ASK/FSK), estimates the **bit length / samples-per-symbol**, and renders the burst as a bit string. Set the decoding (Manchester / PWM / NRZ) until the preamble and a stable structure appear [pohl2018urh][pohl2019autopre]. -4. **Confirm the framing is correct**, not just plausible. The same physical press, captured twice, must demodulate to the same bits (for a fixed-code device) or differ only in the expected counter field (rolling). A demod whose bit count drifts between identical presses means the bit length or coding is still wrong — return to step 3. +4. **Confirm the framing is correct**, not just plausible. The same physical press, captured twice, must demodulate to the same bits (for a fixed-code device) or differ only in the expected counter field (rolling). A demod whose bit count drifts between identical presses means the bit length or coding is still wrong, return to step 3. 5. **(Optional) Validate against a hardware demodulator.** Program a YARD Stick One to the recovered settings and receive the same burst, cross-checking the bitstream: ```python @@ -171,17 +171,17 @@ All steps below are passive receive-and-demodulate. They involve no transmission ## Field case -Documented public walkthrough — substitute the values you capture. This is a worked example for the most common class on the band, an EV1527/PT2262-class OOK fixed-code remote (doorbell or socket remote), anchored to rtl_433's published decoder and shipped sample corpus for this exact device class rather than to a live capture of our own [rtl433ev1527]. The modulation family (OOK/ASK), the fixed-code outcome and the per-press repetition are the general, citable behaviour of this device class [rtl433primer][rtl433repo]; the concrete timings below are the ones rtl_433 documents for it, but for any specific unit they must still be re-measured. +Documented public walkthrough, substitute the values you capture. This is a worked example for the most common class on the band, an EV1527/PT2262-class OOK fixed-code remote (doorbell or socket remote), anchored to rtl_433's published decoder and shipped sample corpus for this exact device class rather than to a live capture of our own [rtl433ev1527]. The modulation family (OOK/ASK), the fixed-code outcome and the per-press repetition are the general, citable behaviour of this device class [rtl433primer][rtl433repo]; the concrete timings below are the ones rtl_433 documents for it, but for any specific unit they must still be re-measured. - The carrier sits at **433.92 MHz**; the waterfall shows short OOK bursts (blinking blocks, not two stacked FSK lines) each time the button is pressed. -- rtl_433's decoder for this exact class — `Generic Remote SC226x EV1527` (`src/devices/generic_remote.c`) — characterises the burst as **OOK_PWM** with a short pulse of **464 µs** and a long pulse of **1404 µs** (tolerance 200 µs), i.e. a PWM bit period of roughly **1868 µs (~535 baud)** [rtl433ev1527]. The sibling in-repo EV1527 flex spec (`conf/EV1527-4Button-Universal-Remote.conf`, `m=OOK_PWM s=369 l=1072 g=1400 r=12840 bits>=24 repeats>=3`) records the same OOK_PWM family with comparable timings for a 4-button variant [rtl433ev1527]. -- Loaded into URH, autodetect labels the signal **ASK**, bit length `[FILL: samples-per-symbol]`, and resolves the frame to **25** bits per burst — 24 data bits plus a trailing always-1 stop bit, per the decoder's `bits != 25` / "Last bit (MSB here) is always 1" framing check [rtl433ev1527]. The 24-bit data word repeats several times per press: rtl_433's EV1527 family confirms a row by requiring it to recur **≥ 3** times per transmission (`bitbuffer_find_repeated_row(bitbuffer, 3, 24)`) [rtl433ev1527]. -- Two captures of the same button press demodulate to an **identical** bitstream — establishing this as a *fixed code* (the fixed-vs-rolling determination this PHY framing hands to the link/attack layers), so a plain capture-and-replay is the relevant downstream test rather than a RollJam-class technique. The rtl_433_tests corpus (`tests/generic_remote/01/`, with `gfile001.cu8` and its expected `gfile001.json`) ships exactly such a repeated fixed-code burst for this decoder [rtl433ev1527]. +- rtl_433's decoder for this exact class, `Generic Remote SC226x EV1527` (`src/devices/generic_remote.c`), characterises the burst as **OOK_PWM** with a short pulse of **464 µs** and a long pulse of **1404 µs** (tolerance 200 µs), i.e. a PWM bit period of roughly **1868 µs (~535 baud)** [rtl433ev1527]. The sibling in-repo EV1527 flex spec (`conf/EV1527-4Button-Universal-Remote.conf`, `m=OOK_PWM s=369 l=1072 g=1400 r=12840 bits>=24 repeats>=3`) records the same OOK_PWM family with comparable timings for a 4-button variant [rtl433ev1527]. +- Loaded into URH, autodetect labels the signal **ASK**, bit length `[FILL: samples-per-symbol]`, and resolves the frame to **25** bits per burst, 24 data bits plus a trailing always-1 stop bit, per the decoder's `bits != 25` / "Last bit (MSB here) is always 1" framing check [rtl433ev1527]. The 24-bit data word repeats several times per press: rtl_433's EV1527 family confirms a row by requiring it to recur **≥ 3** times per transmission (`bitbuffer_find_repeated_row(bitbuffer, 3, 24)`) [rtl433ev1527]. +- Two captures of the same button press demodulate to an **identical** bitstream, establishing this as a *fixed code* (the fixed-vs-rolling determination this PHY framing hands to the link/attack layers), so a plain capture-and-replay is the relevant downstream test rather than a RollJam-class technique. The rtl_433_tests corpus (`tests/generic_remote/01/`, with `gfile001.cu8` and its expected `gfile001.json`) ships exactly such a repeated fixed-code burst for this decoder [rtl433ev1527]. ## Remediation -Demodulation is auditor-side — there is no "fix" for the ability to recover bits from a clear waveform. The defensive value of this control is what the clean bitstream proves: that **the PHY layer authenticates nothing**. Layered guidance for the parties who can act on it: +Demodulation is auditor-side, there is no "fix" for the ability to recover bits from a clear waveform. The defensive value of this control is what the clean bitstream proves: that **the PHY layer authenticates nothing**. Layered guidance for the parties who can act on it: -- **Developer (device firmware/silicon).** Do not treat a stable, recoverable ID broadcast in the clear as a security property — identification is not authentication. If confidentiality or integrity matters, add it above the PHY (an authenticated/encrypted payload, a true rolling code with an adequate window, a freshness/nonce field), because the waveform itself will always demodulate [ossmann2015rrr][rtl433primer]. Avoid trivially short keyspaces (e.g. 8–12 DIP-switch bits) that a recovered frame format makes brute-forceable. +- **Developer (device firmware/silicon).** Do not treat a stable, recoverable ID broadcast in the clear as a security property, identification is not authentication. If confidentiality or integrity matters, add it above the PHY (an authenticated/encrypted payload, a true rolling code with an adequate window, a freshness/nonce field), because the waveform itself will always demodulate [ossmann2015rrr][rtl433primer]. Avoid trivially short keyspaces (e.g. 8 to 12 DIP-switch bits) that a recovered frame format makes brute-forceable. - **Integrator (product builder).** Choose modules whose security does not rest on obscurity of the modulation or line coding; assume an auditor (and an attacker) can frame the burst with rtl_433 or URH within minutes [pohl2018urh]. Where a clear-text fixed code is unavoidable for a function, ensure that function is not safety- or access-critical, or gate it behind a second, authenticated channel. -- **Operator (deployment).** Recognise that a captured remote, sensor or contact-closure signal can be reproduced from a passive recording; for access-control or safety roles, prefer devices documented to use authenticated rolling codes, and monitor for the replay/jamming the demodulated frame enables downstream. Frame any vendor protocol list as representative — check current advisories and rtl_433's supported-device set, which change often [rtl433repo]. +- **Operator (deployment).** Recognise that a captured remote, sensor or contact-closure signal can be reproduced from a passive recording; for access-control or safety roles, prefer devices documented to use authenticated rolling codes, and monitor for the replay/jamming the demodulated frame enables downstream. Frame any vendor protocol list as representative, check current advisories and rtl_433's supported-device set, which change often [rtl433repo]. diff --git a/src/content/controls/rfsam-subg-sp-01.md b/src/content/controls/rfsam-subg-sp-01.md index 757c2eb..495cdda 100644 --- a/src/content/controls/rfsam-subg-sp-01.md +++ b/src/content/controls/rfsam-subg-sp-01.md @@ -12,8 +12,8 @@ applicability: deferred: false objective: >- Determine whether a sub-GHz device's transmissions can be found and - characterised at the spectrum layer — locating the carrier, classifying the - modulation as OOK/ASK or (G)FSK, and recording the burst timing — so that + characterised at the spectrum layer, locating the carrier, classifying the + modulation as OOK/ASK or (G)FSK, and recording the burst timing, so that later capture and replay controls can act on a known layer-1 target. intro: >- Sub-GHz ISM is where most remotes, sensors, alarms and key fobs live. The @@ -28,7 +28,7 @@ prerequisites: software: - 'gqrx (waterfall/spectrum view), rtl_433 (live device scan and pulse analyzer), optionally catnip for the CatSniffer SX1262' signal: - freq: '315 MHz (NA/Asia remotes, TPMS) · 433.92 MHz (global workhorse) · 868 MHz (EU SRD, wM-Bus) · 915 MHz (US ISM, 902–928)' + freq: '315 MHz (NA/Asia remotes, TPMS) · 433.92 MHz (global workhorse) · 868 MHz (EU SRD, wM-Bus) · 915 MHz (US ISM, 902 to 928)' bandwidth: 'Narrow ISM channels; a few hundred kHz per device burst' modulation: 'OOK/ASK (carrier blinks the bits) or (G)FSK (carrier shifts between two tones); no spread spectrum' skill: beginner @@ -56,7 +56,7 @@ references: url: 'https://threatpost.com/hack-disarms-simplisafes-home-wireless-security-systems/116334/' type: blog - key: rtl433 - title: 'rtl_433 — generic data receiver for the 433.92/315/868/915 MHz ISM bands' + title: 'rtl_433: generic data receiver for the 433.92/315/868/915 MHz ISM bands' authors: 'Benjamin Larsson (merbanan) et al.' venue: GitHub year: 2026 @@ -69,14 +69,14 @@ references: url: 'https://triq.org/rtl_433/OPERATION.html' type: tool - key: gqrx - title: 'Gqrx — software defined radio receiver (GNU Radio + Qt)' + title: 'Gqrx: software defined radio receiver (GNU Radio + Qt)' authors: A. Csete (csete) et al. venue: GitHub year: 2026 url: 'https://github.com/gqrx-sdr/gqrx' type: tool - key: fccid - title: 'FCC ID Search — operating frequency, modulation and test exhibits by FCC ID' + title: 'FCC ID Search: operating frequency, modulation and test exhibits by FCC ID' venue: Federal Communications Commission (OET) year: 2026 url: 'https://www.fcc.gov/oet/ea/fccid' @@ -98,17 +98,17 @@ lastResearched: 2026-06-14 --- ## Mechanism -Unlicensed short-range devices cluster in a handful of regional ISM slices well below 1.7 GHz: 315 MHz (North America/Asia remotes and TPMS), 433.92 MHz (the global workhorse — remotes, sensors, alarms), 868 MHz (EU SRD — wM-Bus meters, smart-home) and 915 MHz (US ISM, 902–928). Because the whole band sits below 1 GHz, a cheap RTL-SDR can see it end to end; there is no spread spectrum here, so once you know the centre frequency and rough baud the signals are simple to demodulate [[ossmann2015rapid]]. +Unlicensed short-range devices cluster in a handful of regional ISM slices well below 1.7 GHz: 315 MHz (North America/Asia remotes and TPMS), 433.92 MHz (the global workhorse, remotes, sensors, alarms), 868 MHz (EU SRD, wM-Bus meters, smart-home) and 915 MHz (US ISM, 902 to 928). Because the whole band sits below 1 GHz, a cheap RTL-SDR can see it end to end; there is no spread spectrum here, so once you know the centre frequency and rough baud the signals are simple to demodulate [[ossmann2015rapid]]. -Almost every device in this space keys its bits with **OOK/ASK** (on-off keying — the carrier blinks the bits, the cheapest thing to build) or **(G)FSK** (the carrier shifts between two frequencies). On a waterfall the two are visually distinct: OOK looks like blinking blocks at a single frequency, FSK like two stacked lines. Bits are usually PWM/Manchester/PPM at a few hundred to a few thousand baud, sent as short bursts that often repeat several times per press for reliability [[ossmann2015rapid]]. +Almost every device in this space keys its bits with **OOK/ASK** (on-off keying, the carrier blinks the bits, the cheapest thing to build) or **(G)FSK** (the carrier shifts between two frequencies). On a waterfall the two are visually distinct: OOK looks like blinking blocks at a single frequency, FSK like two stacked lines. Bits are usually PWM/Manchester/PPM at a few hundred to a few thousand baud, sent as short bursts that often repeat several times per press for reliability [[ossmann2015rapid]]. -The discovery method this control follows is Ossmann's "Rapid Radio Reversing": use a wideband SDR (HackRF) to **find and characterise** the signal — frequency, modulation, timing — then drop to a narrowband CC1101-class transceiver (YARD Stick One + rfcat) to **work it** at the recovered layer-1 settings. Ossmann's point is that SDR is the most valuable single tool for finding the signal, but a non-SDR transceiver is often faster for the receive/transmit work once the parameters are known; the two are complementary [[ossmann2015rapid]]. +The discovery method this control follows is Ossmann's "Rapid Radio Reversing": use a wideband SDR (HackRF) to **find and characterise** the signal, frequency, modulation, timing, then drop to a narrowband CC1101-class transceiver (YARD Stick One + rfcat) to **work it** at the recovered layer-1 settings. Ossmann's point is that SDR is the most valuable single tool for finding the signal, but a non-SDR transceiver is often faster for the receive/transmit work once the parameters are known; the two are complementary [[ossmann2015rapid]]. -Much of the layer-1 answer can also be read off the device before any RF. The FCC ID printed on a US-market label resolves the exact operating frequency, modulation and a full test report through the FCC's equipment-authorization search (or mirrors such as fccid.io) — frequently confirming the band and modulation without touching a radio [[fccid]]. That label lookup belongs to the IG step; this control confirms it on the air. +Much of the layer-1 answer can also be read off the device before any RF. The FCC ID printed on a US-market label resolves the exact operating frequency, modulation and a full test report through the FCC's equipment-authorization search (or mirrors such as fccid.io), frequently confirming the band and modulation without touching a radio [[fccid]]. That label lookup belongs to the IG step; this control confirms it on the air. -Two complementary on-air views make the discovery fast. A **gqrx** waterfall shows the live carrier, the modulation shape and the rough burst timing as you trigger the device [[gqrx]]. Pointing **rtl_433** at the band turns every burst it already has a decoder for into a live JSON line naming the device and frequency — rtl_433 ships ~320 device protocols (representative — the count grows as decoders are added) and defaults to 433.92 MHz — which is often the fastest way to confirm what is on the air before committing a capture tool [[rtl433]]. For an unrecognised gadget rtl_433 still shows energy but no decode; its pulse analyzer (`-A`) then reports the pulse/gap timing so you can estimate the encoding by hand [[rtl433ops]]. +Two complementary on-air views make the discovery fast. A **gqrx** waterfall shows the live carrier, the modulation shape and the rough burst timing as you trigger the device [[gqrx]]. Pointing **rtl_433** at the band turns every burst it already has a decoder for into a live JSON line naming the device and frequency, rtl_433 ships ~320 device protocols (representative, the count grows as decoders are added) and defaults to 433.92 MHz, which is often the fastest way to confirm what is on the air before committing a capture tool [[rtl433]]. For an unrecognised gadget rtl_433 still shows energy but no decode; its pulse analyzer (`-A`) then reports the pulse/gap timing so you can estimate the encoding by hand [[rtl433ops]]. -This is a capability/observation control, not an attack: it establishes that a target's transmissions are findable and classifiable. The finding it sets up — and which later SUBG controls act on — is that any device transmitting unauthenticated OOK/FSK bursts in the clear (most cheap ISM remotes and sensors) is replayable or forgeable once characterised [[ossmann2016simplisafe]]. +This is a capability/observation control, not an attack: it establishes that a target's transmissions are findable and classifiable. The finding it sets up, and which later SUBG controls act on, is that any device transmitting unauthenticated OOK/FSK bursts in the clear (most cheap ISM remotes and sensors) is replayable or forgeable once characterised [[ossmann2016simplisafe]]. ## Procedure @@ -131,7 +131,7 @@ This is a capability/observation control, not an attack: it establishes that a t ```bash rtl_433 -f 433.92M -F json ``` - Expected (a recognised device, e.g. a weather sensor or TPMS) — one JSON line per burst with named fields: + Expected (a recognised device, e.g. a weather sensor or TPMS), one JSON line per burst with named fields: ```json {"time":"2026-06-14 12:00:00","model":"Acurite-Tower","id":1234,"channel":"A","temperature_C":21.3,"humidity":48,"battery_ok":1} ``` @@ -144,26 +144,26 @@ This is a capability/observation control, not an attack: it establishes that a t ```bash rtl_433 -f 433.92M -R 0 -A ``` - Expected: a statistical overview of pulse width, gap width and period, with a guessed coding (OOK_PWM / OOK_PCM etc.) and an estimated bit rate — the layer-1 numbers you need to configure the next tool. + Expected: a statistical overview of pulse width, gap width and period, with a guessed coding (OOK_PWM / OOK_PCM etc.) and an estimated bit rate, the layer-1 numbers you need to configure the next tool. -5. **(Optional) Board-native spectrum without an SDR.** Drive the CatSniffer's SX1262 as a sub-GHz spectrum scanner with catnip to find activity on 433/868/915 MHz from the board alone — a CatSniffer alternative to the gqrx waterfall for locating where a device transmits. +5. **(Optional) Board-native spectrum without an SDR.** Drive the CatSniffer's SX1262 as a sub-GHz spectrum scanner with catnip to find activity on 433/868/915 MHz from the board alone, a CatSniffer alternative to the gqrx waterfall for locating where a device transmits. -6. **Record the layer-1 profile and (optionally) verify it on a CC1101 radio.** Write down centre frequency, modulation, shortest pulse (→ baud) and burst-repeat count. To confirm the parameters are right, configure a YARD Stick One with rfcat at those settings and receive the burst — Ossmann's "work it" half of the flow (this hands off to the SUBG capture/LL control). Expected: the same burst received cleanly at the chosen frequency/modulation/baud confirms the profile. +6. **Record the layer-1 profile and (optionally) verify it on a CC1101 radio.** Write down centre frequency, modulation, shortest pulse (→ baud) and burst-repeat count. To confirm the parameters are right, configure a YARD Stick One with rfcat at those settings and receive the burst, Ossmann's "work it" half of the flow (this hands off to the SUBG capture/LL control). Expected: the same burst received cleanly at the chosen frequency/modulation/baud confirms the profile. ## Field case The clearest worked example of this discover-then-work-it flow is Ossmann's "Low Cost SimpliSafe Attacks" follow-up to Andrew Zonenberg's (IOActive) SimpliSafe research [[ossmann2016simplisafe]] [[zonenberg2016simplisafe]]. -Zonenberg's original work used a logic analyser to reverse the protocol and a custom microcontroller (~$250 of SimpliSafe parts plus boards) to passively capture the "PIN entered" packet and replay it on demand to disarm the alarm [[zonenberg2016simplisafe]]. Ossmann then reproduced and undercut it with off-the-shelf RF tools at less than half the cost: he used a **HackRF One** to monitor the keypad transmissions and characterise the signal, then a **YARD Stick One (~$100) with rfcat** — plus **inspectrum** to visualise the waveform and Python to decode — to receive and replay [[ossmann2016simplisafe]]. +Zonenberg's original work used a logic analyser to reverse the protocol and a custom microcontroller (~$250 of SimpliSafe parts plus boards) to passively capture the "PIN entered" packet and replay it on demand to disarm the alarm [[zonenberg2016simplisafe]]. Ossmann then reproduced and undercut it with off-the-shelf RF tools at less than half the cost: he used a **HackRF One** to monitor the keypad transmissions and characterise the signal, then a **YARD Stick One (~$100) with rfcat**, plus **inspectrum** to visualise the waveform and Python to decode, to receive and replay [[ossmann2016simplisafe]]. -The layer-1 profile he recovered at the spectrum step: the keypad transmitted on **433 MHz** using **amplitude-shift keying** (Ossmann notes Zonenberg labelled it OOK and that "the difference between ASK and OOK is subtle"), with an uncommon **Pulse Interval and Width Modulation (PIWM)** encoding. Visualising the waveform, he identified the frequency and modulation and "within seconds" was decoding raw symbols; working out the PIWM encoding from the packet data was the hard part, taking roughly two hours [[ossmann2016simplisafe]]. That spectrum/PHY characterisation — frequency, ASK, burst timing — is exactly the output this control produces; the replay/disarm that followed is the downstream SUBG attack control, performed only against equipment under the tester's authority. +The layer-1 profile he recovered at the spectrum step: the keypad transmitted on **433 MHz** using **amplitude-shift keying** (Ossmann notes Zonenberg labelled it OOK and that "the difference between ASK and OOK is subtle"), with an uncommon **Pulse Interval and Width Modulation (PIWM)** encoding. Visualising the waveform, he identified the frequency and modulation and "within seconds" was decoding raw symbols; working out the PIWM encoding from the packet data was the hard part, taking roughly two hours [[ossmann2016simplisafe]]. That spectrum/PHY characterisation, frequency, ASK, burst timing, is exactly the output this control produces; the replay/disarm that followed is the downstream SUBG attack control, performed only against equipment under the tester's authority. The same discover-then-work-it flow applies unchanged to a garage/gate remote, a TPMS sensor, or a 433 MHz weather station: a representative weather sensor surfaces immediately as a named `rtl_433 -f 433.92M -F json` line (`model`, `id`, `temperature_C`), confirming band and protocol with no SDR waterfall reading at all. ## Remediation -Discovery feasibility is a baseline finding rather than a fixable defect — the air is observable to anyone with a $30 receiver. The mitigations live one layer up, at what the burst *contains*, and are layered by who owns the design: +Discovery feasibility is a baseline finding rather than a fixable defect, the air is observable to anyone with a $30 receiver. The mitigations live one layer up, at what the burst *contains*, and are layered by who owns the design: -- **Developer (device/firmware):** Do not rely on the burst being unseen. Treat every transmitted frame as fully observable: do not put secrets, fixed unlock codes, or static identifiers in the clear. Where a control action matters (locks, alarms, garage doors), use a rolling/hopping code or an authenticated, freshness-protected message so that a captured burst cannot be replayed — the SimpliSafe class of replay attack exists precisely because the disarm packet was static and reusable [[zonenberg2016simplisafe]]. -- **Integrator (product/system):** Choose modules whose protocol is encrypted and anti-replay rather than fixed-code OOK, and verify the choice empirically — run the gqrx + rtl_433 sweep above against your own unit and confirm the security-relevant frames are not trivially decoded or replayable. Cross-check the FCC grant to confirm the radio behaves as the datasheet claims [[fccid]]. +- **Developer (device/firmware):** Do not rely on the burst being unseen. Treat every transmitted frame as fully observable: do not put secrets, fixed unlock codes, or static identifiers in the clear. Where a control action matters (locks, alarms, garage doors), use a rolling/hopping code or an authenticated, freshness-protected message so that a captured burst cannot be replayed, the SimpliSafe class of replay attack exists precisely because the disarm packet was static and reusable [[zonenberg2016simplisafe]]. +- **Integrator (product/system):** Choose modules whose protocol is encrypted and anti-replay rather than fixed-code OOK, and verify the choice empirically, run the gqrx + rtl_433 sweep above against your own unit and confirm the security-relevant frames are not trivially decoded or replayable. Cross-check the FCC grant to confirm the radio behaves as the datasheet claims [[fccid]]. - **Operator (deployment):** Assume the link is in the clear and observable from outside the premises; do not treat "it's wireless and proprietary" as confidentiality. For high-value functions, prefer devices with documented rolling-code/authenticated links, and monitor for the abnormal repeated bursts that capture-and-replay or jam-and-capture tooling produces. diff --git a/src/content/controls/rfsam-thread-cr-01.md b/src/content/controls/rfsam-thread-cr-01.md index ebbb29b..c5e2381 100644 --- a/src/content/controls/rfsam-thread-cr-01.md +++ b/src/content/controls/rfsam-thread-cr-01.md @@ -9,9 +9,9 @@ applicability: - Matter-over-Thread deferred: false objective: >- - Determine whether the credentials that gate a Thread mesh — the Thread network + Determine whether the credentials that gate a Thread mesh, the Thread network key and the commissioning secrets that distribute it (the Commissioner PSKc, the - Joiner PSKd, and, for Matter devices, the SPAKE2+ setup passcode) — are + Joiner PSKd, and, for Matter devices, the SPAKE2+ setup passcode), are provisioned and protected such that an attacker cannot recover the network key or join the mesh from a weak, default, or exposed credential. intro: >- @@ -30,7 +30,7 @@ prerequisites: - 'Wireshark (802.15.4 + Thread/6LoWPAN/MLE dissector, with the 802.15.4 decryption-keys table)' - 'nRF Sniffer for 802.15.4 / pyspinel for capture; chip-tool (Matter SDK) for setup-code / PASE testing' signal: - freq: '2.405–2.480 GHz (IEEE 802.15.4 channels 11–26, 5 MHz spacing; a Thread network sits on one channel)' + freq: '2.405 to 2.480 GHz (IEEE 802.15.4 channels 11 to 26, 5 MHz spacing; a Thread network sits on one channel)' bandwidth: '2 MHz occupied per 5 MHz channel' modulation: 'O-QPSK (DSSS), 250 kbit/s' skill: advanced @@ -50,7 +50,7 @@ attacks: brute force against a random 27-bit passcode. summary: >- SPAKE2+ keys the first Matter session entirely from the 27-bit setup - passcode; that passcode — not the cipher — is the weak link when it is + passcode; that passcode, not the cipher, is the weak link when it is default, guessable, or exposed. - name: Thread commissioning credential recovery (PSKc / PSKd) refs: @@ -77,14 +77,14 @@ attacks: - cve-2024-3297 impact: >- Makes a commissioned Matter device unresponsive until it is power-cycled by - replaying manipulated CASE Sigma1 messages — a denial of the operational + replaying manipulated CASE Sigma1 messages, a denial of the operational session rather than a credential compromise. preconditions: >- Adjacent-network reach to a device running a Matter stack before Matter 1.1. summary: >- A replay weakness in CASE session establishment (before Matter 1.1) that bounds confidence in the operational handshake; included as a - representative advisory — check current CSA advisories. + representative advisory, check current CSA advisories. references: - key: matter-core-spec title: 'Matter Core Specification, Version 1.0' @@ -126,7 +126,7 @@ references: url: 'https://nvd.nist.gov/vuln/detail/CVE-2024-3454' type: cve - key: matter-chip-tool-guide - title: 'Working with the CHIP Tool — Step 5: Determine Matter device''s discriminator and setup PIN code' + title: 'Working with the CHIP Tool: Step 5: Determine Matter device''s discriminator and setup PIN code' authors: Project CHIP / connectedhomeip venue: 'project-chip/connectedhomeip (docs/development_controllers/chip-tool/chip_tool_guide.md)' year: 2024 @@ -148,17 +148,17 @@ lastResearched: 2026-06-14 ## Mechanism -A Thread network is an IPv6 mesh whose MAC payloads are encrypted with AES-128-CCM* under a single shared **Thread network key**; possession of that key is what separates an insider from an outsider, and it is also what lets a passive capture be decrypted [thread-commissioning-wp]. The cipher is not the weak point — recovering the *credentials that distribute the key* is. New devices obtain the key through the **Mesh Commissioning Protocol (MeshCoP)**: a Joiner opens a DTLS session to the Commissioner and authenticates with a per-device Joiner credential (**PSKd**), while the Commissioner itself is admitted to the network using the **PSKc** (a pre-shared key derived from a commissioning passphrase); the handshake that protects this exchange is an EC-JPAKE password-authenticated key exchange over P-256 [thread-commissioning-wp][thread-meshcop-verification]. Because MeshCoP is a PAKE bootstrapped from these secrets, the practical exposure is the *strength and handling* of PSKc/PSKd — a default, printed, or low-entropy credential — not a break of the handshake; a formal symbolic analysis (ProVerif) of MeshCoP models exactly this commissioning protocol and its trust assumptions, and reports no exploitable weakness in the modelled handshake — it is cited here only to anchor that MeshCoP/EC-JPAKE is the modelled commissioning protocol, not a named attack [thread-meshcop-verification]. +A Thread network is an IPv6 mesh whose MAC payloads are encrypted with AES-128-CCM* under a single shared **Thread network key**; possession of that key is what separates an insider from an outsider, and it is also what lets a passive capture be decrypted [thread-commissioning-wp]. The cipher is not the weak point, recovering the *credentials that distribute the key* is. New devices obtain the key through the **Mesh Commissioning Protocol (MeshCoP)**: a Joiner opens a DTLS session to the Commissioner and authenticates with a per-device Joiner credential (**PSKd**), while the Commissioner itself is admitted to the network using the **PSKc** (a pre-shared key derived from a commissioning passphrase); the handshake that protects this exchange is an EC-JPAKE password-authenticated key exchange over P-256 [thread-commissioning-wp][thread-meshcop-verification]. Because MeshCoP is a PAKE bootstrapped from these secrets, the practical exposure is the *strength and handling* of PSKc/PSKd, a default, printed, or low-entropy credential, not a break of the handshake; a formal symbolic analysis (ProVerif) of MeshCoP models exactly this commissioning protocol and its trust assumptions, and reports no exploitable weakness in the modelled handshake, it is cited here only to anchor that MeshCoP/EC-JPAKE is the modelled commissioning protocol, not a named attack [thread-meshcop-verification]. -On a **Matter-over-Thread** device the same network key is reached through a second credential. Matter commissioning runs **PASE (Passcode-Authenticated Session Establishment)**, which is **SPAKE2+** over P-256 keyed entirely from a **27-bit setup passcode** (the printed 8-digit PIN); the device stores a SPAKE2+ *verifier*, not the passcode itself, and PASE only runs while a commissioning window is open [matter-core-spec][matter-security-analysis]. Once commissioned, all operational sessions use **CASE** — certificate-authenticated (a Node Operational Certificate under a fabric Root CA), not the passcode [matter-core-spec]. So for Matter the passcode, not the cipher, is the weak link: a default, guessable, or photographed setup code collapses the search, and a verifier extracted from an insecure device is open to offline recovery given the low passcode entropy [matter-security-analysis]. Online guessing is bounded by the spec (failed-PASE limits and a time-boxed commissioning window) and the obvious codes are disallowed — the reference connectedhomeip implementation rejects `00000000`, each repeated-digit value (`11111111` … `88888888`), `12345678` and `87654321`, and any value outside the `00000001`–`99999998` range — so the realistic win is a *weak vendor default or an exposed onboarding payload*, not brute force against a random code [matter-core-spec][matter-security-analysis]. +On a **Matter-over-Thread** device the same network key is reached through a second credential. Matter commissioning runs **PASE (Passcode-Authenticated Session Establishment)**, which is **SPAKE2+** over P-256 keyed entirely from a **27-bit setup passcode** (the printed 8-digit PIN); the device stores a SPAKE2+ *verifier*, not the passcode itself, and PASE only runs while a commissioning window is open [matter-core-spec][matter-security-analysis]. Once commissioned, all operational sessions use **CASE**, certificate-authenticated (a Node Operational Certificate under a fabric Root CA), not the passcode [matter-core-spec]. So for Matter the passcode, not the cipher, is the weak link: a default, guessable, or photographed setup code collapses the search, and a verifier extracted from an insecure device is open to offline recovery given the low passcode entropy [matter-security-analysis]. Online guessing is bounded by the spec (failed-PASE limits and a time-boxed commissioning window) and the obvious codes are disallowed, the reference connectedhomeip implementation rejects `00000000`, each repeated-digit value (`11111111` … `88888888`), `12345678` and `87654321`, and any value outside the `00000001` to `99999998` range, so the realistic win is a *weak vendor default or an exposed onboarding payload*, not brute force against a random code [matter-core-spec][matter-security-analysis]. Two further advisories bound confidence in the surrounding handshakes and should be treated as representative (check current CSA advisories): **CVE-2024-3297** lets an attacker replay manipulated **CASE Sigma1** messages to render a device unresponsive until power-cycled, in Matter stacks before 1.1 (a DoS of the operational session, not a credential break) [cve-2024-3297]; and **CVE-2024-3454** is an intra-fabric **footprinting** disclosure in the connectedhomeip SDK (Matter 1.2) where a same-fabric party learns information the protocol intends to hide [cve-2024-3454]. Neither recovers the network key, but both are worth recording when profiling a device's stack version. ## Procedure -Run every active or decrypt step only against your own equipment, test devices, and credentials you are authorised to hold — recovering a network key or driving PASE against a device you do not own is out of scope for an unauthorised tester. +Run every active or decrypt step only against your own equipment, test devices, and credentials you are authorised to hold, recovering a network key or driving PASE against a device you do not own is out of scope for an unauthorised tester. -1. **Capture the mesh and confirm it is Thread on its channel.** Park an 802.15.4 radio on the target channel (11–26) and stream frames into Wireshark. +1. **Capture the mesh and confirm it is Thread on its channel.** Park an 802.15.4 radio on the target channel (11 to 26) and stream frames into Wireshark. ```bash # nRF52840 with the nRF Sniffer for 802.15.4 extcap, or via pyspinel: python sniffer.py -c 15 -u /dev/ttyACM0 -b 460800 --crc -o - | wireshark -k -i - @@ -166,31 +166,31 @@ Run every active or decrypt step only against your own equipment, test devices, Expected: 802.15.4 frames in Wireshark. Thread shows 6LoWPAN + MLE (and IPv6) above the MAC; the MAC payload is shown encrypted until you supply the key. Read the channel, PAN ID, Extended PAN ID and Network Name from beacons/MLE without any key. 2. **Establish whether you hold (or can obtain) the network key, and that it decrypts the capture.** Enter the candidate Thread network key into Wireshark's 802.15.4 decryption-keys table (Preferences -> Protocols -> IEEE 802.15.4 -> Decryption Keys; key index/hash per the MLE security suite). - - If the mesh becomes readable (6LoWPAN/MLE/IPv6 in clear), the key is valid — the finding is *how you came to hold it* (default/exposed/weak commissioning credential), not that AES was broken. - - If it stays opaque, the key is unknown — proceed to assess the commissioning credentials below. + - If the mesh becomes readable (6LoWPAN/MLE/IPv6 in clear), the key is valid, the finding is *how you came to hold it* (default/exposed/weak commissioning credential), not that AES was broken. + - If it stays opaque, the key is unknown, proceed to assess the commissioning credentials below. -3. **Assess the Thread commissioning posture (PSKc / PSKd).** Determine how the Joiner credential and Commissioner passphrase are set: are they vendor defaults, printed on the label, shared across a product line, or low-entropy? Is a Commissioner / Border Agent reachable, and is the commissioning window left open? Record the credential source and entropy — a default or printed PSKd that admits a Joiner is the finding [thread-commissioning-wp]. +3. **Assess the Thread commissioning posture (PSKc / PSKd).** Determine how the Joiner credential and Commissioner passphrase are set: are they vendor defaults, printed on the label, shared across a product line, or low-entropy? Is a Commissioner / Border Agent reachable, and is the commissioning window left open? Record the credential source and entropy, a default or printed PSKd that admits a Joiner is the finding [thread-commissioning-wp]. 4. **For a Matter device, decode the onboarding payload and test the setup passcode (authorised devices only).** Recover the passcode, discriminator and VID/PID from the printed QR / 11-digit manual code, then drive PASE with chip-tool against a *device you own* using the candidate (printed value or a known vendor default): ```bash # Pair over BLE onto Thread using the on-label setup code; this exercises PASE (SPAKE2+): chip-tool pairing ble-thread hex: ``` - Expected: success means the passcode admitted a commissioner (commission onto an attacker-controlled fabric on your own bench is the demonstration); on a Matter-over-Thread device this also yields the operational Thread credentials. Repeated failure eventually drives the node out of commissioning mode — that closure is itself a positive finding about the rate-limit posture. A *default or printed* code succeeding is the weakness; a *random* code resisting guessing is the expected, healthy result. + Expected: success means the passcode admitted a commissioner (commission onto an attacker-controlled fabric on your own bench is the demonstration); on a Matter-over-Thread device this also yields the operational Thread credentials. Repeated failure eventually drives the node out of commissioning mode, that closure is itself a positive finding about the rate-limit posture. A *default or printed* code succeeding is the weakness; a *random* code resisting guessing is the expected, healthy result. 5. **Record the stack version against the representative advisories.** Note the SoC/SDK (e.g. nRF52840 / EFR32 / ESP32-H2) and whether the Matter stack predates 1.1 (CVE-2024-3297) or 1.2 (CVE-2024-3454); these do not recover the key but characterise the operational-session and footprinting exposure [cve-2024-3297][cve-2024-3454]. ## Field case -This walkthrough is grounded in the Matter SDK's own documented example onboarding payload, so the decoded values below are public reference data — not a measured engagement against a third-party device. Any value still marked `[FILL: …]` is a capture-specific placeholder and must not be treated as an observed finding. +This walkthrough is grounded in the Matter SDK's own documented example onboarding payload, so the decoded values below are public reference data, not a measured engagement against a third-party device. Any value still marked `[FILL: …]` is a capture-specific placeholder and must not be treated as an observed finding. -The Matter SDK's chip-tool guide documents how to recover a device's onboarding parameters from its printed payload, using the SDK reference example payload — QR `MT:Y.K9042C00KA0648G00` / manual pairing code `749701123365521327694` — as its worked case [matter-chip-tool-guide]. Decoding that payload (the guide's "Step 5: Determine Matter device's discriminator and setup PIN code") yields a setup passcode of `20202021`, discriminator `3840 (0xF00)`, Vendor Id `65521 (0xFFF1)` and Product Id `32768 (0x8000)` [matter-chip-tool-guide]. An 802.15.4 capture on channel `[FILL: channel 11–26]` shows 6LoWPAN + MLE frames — confirming Thread, not Zigbee — with the MAC payload encrypted; without the network key, Wireshark leaves the payloads opaque (the expected, healthy state). +The Matter SDK's chip-tool guide documents how to recover a device's onboarding parameters from its printed payload, using the SDK reference example payload, QR `MT:Y.K9042C00KA0648G00` / manual pairing code `749701123365521327694`, as its worked case [matter-chip-tool-guide]. Decoding that payload (the guide's "Step 5: Determine Matter device's discriminator and setup PIN code") yields a setup passcode of `20202021`, discriminator `3840 (0xF00)`, Vendor Id `65521 (0xFFF1)` and Product Id `32768 (0x8000)` [matter-chip-tool-guide]. An 802.15.4 capture on channel `[FILL: channel 11 to 26]` shows 6LoWPAN + MLE frames, confirming Thread, not Zigbee, with the MAC payload encrypted; without the network key, Wireshark leaves the payloads opaque (the expected, healthy state). -With a commissioning window open, the same guide drives PASE over BLE onto Thread with that on-label code via `./chip-tool pairing ble-thread 1 hex: 20202021 3840`, where `20202021` is the decoded setup passcode and `3840` the discriminator [matter-chip-tool-guide]. A successful pairing returns the operational Thread dataset, which then decrypts the capture in Wireshark — demonstrating that the entire chain hinges on the setup code, not on the AES-CCM* link layer. The audit question that determines criticality is whether that passcode is a unique high-entropy per-device value or a shared/guessable default. Here it is the latter: `20202021` (with discriminator `3840` and VID/PID `0xFFF1/0x8000`) is the SDK's shared example/test value, baked into the reference apps and reused across SDK documentation and sample builds [matter-chip-tool-guide] — exactly the kind of common, non-unique credential a real device must never ship, so on production hardware its presence would be a genuine exposure rather than a hardening note. +With a commissioning window open, the same guide drives PASE over BLE onto Thread with that on-label code via `./chip-tool pairing ble-thread 1 hex: 20202021 3840`, where `20202021` is the decoded setup passcode and `3840` the discriminator [matter-chip-tool-guide]. A successful pairing returns the operational Thread dataset, which then decrypts the capture in Wireshark, demonstrating that the entire chain hinges on the setup code, not on the AES-CCM* link layer. The audit question that determines criticality is whether that passcode is a unique high-entropy per-device value or a shared/guessable default. Here it is the latter: `20202021` (with discriminator `3840` and VID/PID `0xFFF1/0x8000`) is the SDK's shared example/test value, baked into the reference apps and reused across SDK documentation and sample builds [matter-chip-tool-guide], exactly the kind of common, non-unique credential a real device must never ship, so on production hardware its presence would be a genuine exposure rather than a hardening note. ## Remediation -**Developer (device / stack).** Provision a unique, high-entropy setup passcode per device (never a shared default, never one of the spec-prohibited codes) and store only the SPAKE2+ *verifier*, never the passcode, in device flash [matter-core-spec]. Enforce the spec's PASE failed-attempt limit and time-boxed commissioning window so online guessing stays bounded [matter-core-spec]. Keep the Matter stack current — at minimum past the versions named in CVE-2024-3297 (CASE Sigma1 replay, ≥ 1.1) and CVE-2024-3454 (intra-fabric footprinting) [cve-2024-3297][cve-2024-3454]. On the Thread side, use per-device Joiner credentials (PSKd) with real entropy and never ship a common PSKc/PSKd across a product line [thread-commissioning-wp]. +**Developer (device / stack).** Provision a unique, high-entropy setup passcode per device (never a shared default, never one of the spec-prohibited codes) and store only the SPAKE2+ *verifier*, never the passcode, in device flash [matter-core-spec]. Enforce the spec's PASE failed-attempt limit and time-boxed commissioning window so online guessing stays bounded [matter-core-spec]. Keep the Matter stack current, at minimum past the versions named in CVE-2024-3297 (CASE Sigma1 replay, ≥ 1.1) and CVE-2024-3454 (intra-fabric footprinting) [cve-2024-3297][cve-2024-3454]. On the Thread side, use per-device Joiner credentials (PSKd) with real entropy and never ship a common PSKc/PSKd across a product line [thread-commissioning-wp]. **Integrator (product / fabric).** Treat the printed onboarding payload as a secret: do not log, photograph into asset systems, or expose setup codes; rotate or retire them after commissioning where the platform allows. Keep the commissioning window closed except during an intended onboarding, and prefer per-device credentials so one leaked code compromises one device, not a fleet. diff --git a/src/content/controls/rfsam-thread-ll-01.md b/src/content/controls/rfsam-thread-ll-01.md index 7fb520e..f8a674f 100644 --- a/src/content/controls/rfsam-thread-ll-01.md +++ b/src/content/controls/rfsam-thread-ll-01.md @@ -10,8 +10,8 @@ applicability: deferred: false objective: >- Determine what network-identifying and commissioning-posture data a Thread mesh - leaks at the link layer to an unauthenticated 802.15.4 sniffer — PAN ID, Extended - PAN ID, Network Name, channel and steering/commissioning state — and whether the + leaks at the link layer to an unauthenticated 802.15.4 sniffer, PAN ID, Extended + PAN ID, Network Name, channel and steering/commissioning state, and whether the commissioning credential (PSKc/Joiner PSKd) or onboarding window is exposed, default, or guessable, without breaking the network key. intro: >- @@ -28,7 +28,7 @@ prerequisites: software: - 'nRF Sniffer for 802.15.4 (Wireshark extcap), pyspinel sniffer.py, or Minino capture; Wireshark with its 802.15.4 / 6LoWPAN / MLE dissectors' signal: - freq: '2.405–2.480 GHz (16 channels, 11–26, 5 MHz spacing); one Thread network occupies a single channel' + freq: '2.405 to 2.480 GHz (16 channels, 11 to 26, 5 MHz spacing); one Thread network occupies a single channel' bandwidth: '~2 MHz occupied per channel (5 MHz channel spacing)' modulation: 'IEEE 802.15.4 O-QPSK (DSSS), 250 kbit/s' skill: intermediate @@ -40,7 +40,7 @@ attacks: impact: >- An unauthenticated sniffer recovers the PAN ID, Extended PAN ID and human-readable Network Name, and can fingerprint the deployment and infer - mesh structure from MLE traffic — all without the network key. + mesh structure from MLE traffic, all without the network key. preconditions: An 802.15.4 sniffer parked on the target channel; an active mesh emitting beacons / MLE discovery responses. summary: >- Thread answers active scans with beacons carrying PAN ID, XPAN ID and Network @@ -80,7 +80,7 @@ references: url: 'https://doi.org/10.1145/3507657.3528544' type: paper - key: ot-network-discovery - title: 'OpenThread Thread Primer — Network Discovery and Formation' + title: 'OpenThread Thread Primer: Network Discovery and Formation' venue: OpenThread (Google / Thread Group) year: 2024 url: 'https://openthread.io/guides/thread-primer/network-discovery' @@ -133,10 +133,10 @@ lastResearched: 2026-06-14 ## Mechanism -Thread is an IPv6 mesh over the IEEE 802.15.4 2.4 GHz O-QPSK PHY (16 channels, 11–26), +Thread is an IPv6 mesh over the IEEE 802.15.4 2.4 GHz O-QPSK PHY (16 channels, 11 to 26), the same radio layer as Zigbee; a single network sits on one channel. The MAC payload is protected with AES-128-CCM* keyed by the Thread network key, so this is **not** a -decryption control — it is an exposure inventory. The link layer still leaks identity: +decryption control, it is an exposure inventory. The link layer still leaks identity: during an active scan, Routers and Router-Eligible End Devices answer a Beacon Request with a beacon that contains the network's **PAN ID, Extended PAN ID (XPAN ID) and human-readable Network Name** in the clear [ot-network-discovery]. Not all MLE @@ -148,13 +148,13 @@ The real attack surface is **commissioning**, not the cipher. Thread admits new via the Mesh Commissioning Protocol (MeshCoP): a Commissioner authenticates to a Border Agent over DTLS using the Pre-Shared Key for the Commissioner (**PSKc**), and a Joiner is admitted with its Joiner credential (**PSKd**), also over DTLS [akestoridis2022thread]. -The Border Agent is discoverable by DNS-SD — a co-located `_meshcop._udp` / +The Border Agent is discoverable by DNS-SD, a co-located `_meshcop._udp` / `_meshcop-e._udp` service is the on-network signature of a reachable commissioning entry point. A symbolic (ProVerif) analysis of MeshCoP models its DTLS-based authentication and its security goals [upadhyay2023meshcop]. The practical link-layer weakness is posture, not protocol breakage: if the commissioner accepts new devices without pinning the joiner's 64-bit IEEE address, an attacker can issue **repeated online password guesses** -during the join window — shown to be impractical for recovering a joiner credential but +during the join window, shown to be impractical for recovering a joiner credential but usable as a **denial-of-service / energy-depletion** attack, optionally amplified by preventing the legitimate device from joining so the user restarts commissioning [akestoridis2022thread]. Open tooling for this analysis (Wireshark Thread dissectors plus @@ -171,13 +171,13 @@ identity, topology and commissioning state the mesh discloses to a passive obser > Authorised testing only: capture passively on networks you own or are explicitly > permitted to assess. Any transmit step (active scan, join attempt) is an active control -> — use your own equipment, test devices, and explicit written permission, ideally inside +>, use your own equipment, test devices, and explicit written permission, ideally inside > RF shielding. 1. **Find the channel.** If unknown, sweep the 2.4 GHz band to spot the active 802.15.4 channel, then park a real radio on it. With a CatSniffer's channel monitor: ```bash - # CatSniffer / catnip — show live 802.15.4 channel activity (11–26) + # CatSniffer / catnip, show live 802.15.4 channel activity (11 to 26) catnip cativity ``` Read off the channel with sustained traffic; that is the mesh's channel. @@ -225,14 +225,14 @@ identity, topology and commissioning state the mesh discloses to a passive obser ## Field case -Illustrative walkthrough — substitute the values your own capture records. On a lab bench +Illustrative walkthrough, substitute the values your own capture records. On a lab bench (your own devices, shielded), a wideband sweep shows activity around channel 15; an nRF52840 RCP driven by `python sniffer.py -c 15 -u /dev/ttyACM0 --crc -b 460800` streams frames into Wireshark, and the filter `wpan.frame_type == 0x0 || mle` isolates the beacon and MLE discovery responses that disclose the network identifiers in the clear, with no key supplied. The identifiers below are not a live bench capture: they are taken from -OpenThread's own published example Active Operational Dataset — the `kTlvBytes` test vector -in `tests/unit/test_dataset.cpp` of openthread/openthread — which makes a concrete, +OpenThread's own published example Active Operational Dataset, the `kTlvBytes` test vector +in `tests/unit/test_dataset.cpp` of openthread/openthread, which makes a concrete, verifiable illustration of exactly the fields a beacon / discovery response leaks [ot-dataset-tlv-vector]. On your own bench, substitute the values your sniffer records: @@ -244,8 +244,8 @@ verifiable illustration of exactly the fields a beacon / discovery response leak `avahi-browse -rt _meshcop._udp` on the same LAN returns a Border Agent entry when a commissioning path is reachable. MAC payloads remain AES-128-CCM* encrypted and are left undecrypted (no network key in scope), so the finding is strictly the -**identifier and commissioning-posture exposure** — exactly the link-layer leak this -control inventories — not message content. +**identifier and commissioning-posture exposure**, exactly the link-layer leak this +control inventories, not message content. ## Remediation @@ -260,12 +260,12 @@ the CASE Sigma1-replay DoS (CVE-2024-3297) [cve-2024-3454][cve-2024-3297]. **Integrator (product / commissioning workflow).** When commissioning, **pin the joiner's 64-bit IEEE address** rather than accepting any device, which removes the multiple-guess / restart-trick amplification [akestoridis2022thread]. Use a strong, -per-device PSKc/PSKd — never a shared default — and distribute the network key out of band. +per-device PSKc/PSKd, never a shared default, and distribute the network key out of band. Keep the commissioning window as short as the workflow allows and close it promptly. **Operator (deployment).** Assume an attacker in RF range already knows the network name, PAN ID and channel; these are not secrets and should not gate trust. Open the commissioning window only when adding a device and confirm it closes afterwards. Periodically re-run this passive inventory to detect unexpected beaconing, a left-open Border Agent, or an -unexpected onboarding window — and treat any of those as posture findings to fix, since the +unexpected onboarding window, and treat any of those as posture findings to fix, since the strong link crypto means the exposure, not the cipher, is the way in. diff --git a/src/content/controls/rfsam-uwb-at-01.md b/src/content/controls/rfsam-uwb-at-01.md index f3aa1ee..3772095 100644 --- a/src/content/controls/rfsam-uwb-at-01.md +++ b/src/content/controls/rfsam-uwb-at-01.md @@ -13,8 +13,8 @@ applicability: deferred: false objective: >- Determine whether a UWB ranging scheme can be made to report a shorter (or - otherwise manipulated) distance than the true time-of-flight — by physical-layer - distance reduction or by relay — such that a proximity security gate (car + otherwise manipulated) distance than the true time-of-flight, by physical-layer + distance reduction or by relay, such that a proximity security gate (car unlock/start, payment, access) can be satisfied from outside its intended range. intro: >- UWB derives distance from the time-of-flight of sub-nanosecond pulses, not from @@ -23,7 +23,7 @@ intro: >- attack surface is therefore physical: can a receiver be coerced into registering an *earlier* arrival than the true one (shortening the measured distance) without any cryptographic material, or can the whole exchange be relayed? This control - assesses that resilience under authorised testing only — there is no turnkey + assesses that resilience under authorised testing only, there is no turnkey open exploit, so it is engineered against a programmable DW3000 peer. prerequisites: hardware: @@ -34,7 +34,7 @@ prerequisites: - 'foldedtoad/dwm3000 (Qorvo dwt_uwb_driver port) to set the 802.15.4z PHY and run/log two-way ranging' - 'SEEMOO uwb-sniffer firmware + Wireshark (sensniff pipe) to capture frames with picosecond timestamps' signal: - freq: '6489.6 MHz (ch 5) or 7987.2 MHz (ch 9); HRP impulse radio, ~3.1–10.6 GHz band' + freq: '6489.6 MHz (ch 5) or 7987.2 MHz (ch 9); HRP impulse radio, ~3.1 to 10.6 GHz band' bandwidth: '>500 MHz per channel' modulation: 'Impulse radio (sub-nanosecond pulses), 850 kbps / 6.81 Mbps; distance from pulse time-of-flight, STS-authenticated' skill: advanced @@ -44,7 +44,7 @@ attacks: - leu2022ghostpeak impact: >- Reduces the measured distance (demonstrated 12 m to 0 m) on Apple U1 - interoperating with NXP/Qorvo chips, with no cryptographic material — enough + interoperating with NXP/Qorvo chips, with no cryptographic material, enough to satisfy a proximity gate from outside its intended range when it succeeds. preconditions: >- HRP 802.15.4z ranging with a receiver design vulnerable to early-detection of @@ -70,7 +70,7 @@ attacks: refs: - singh2019uwbed impact: >- - Lengthens the measured distance by delaying/annihilating the genuine pulse — + Lengthens the measured distance by delaying/annihilating the genuine pulse, can defeat schemes that fail-open on lost ranging, or be used to mask a relay. preconditions: >- Ability to overshadow or cancel the legitimate pulses at the receiver; the @@ -83,7 +83,7 @@ attacks: - yang2024uwbad impact: >- Selectively and quickly blocks ranging sessions on COTS Apple/NXP/Qorvo - chips — a denial that, where the consumer fails open, becomes a security event + chips, a denial that, where the consumer fails open, becomes a security event (e.g. a lock that defaults to unlocked, or a fallback to a weaker channel). preconditions: >- Exploits the normalized cross-correlation in UWB ranging; demonstrated with @@ -127,7 +127,7 @@ references: url: 'https://standards.ieee.org/ieee/802.15.4z/7460/' type: standard - key: ghostpeakproject - title: 'Ghost Peak — project page, platform and code (DWM3000EVB + nRF52DK)' + title: 'Ghost Peak: project page, platform and code (DWM3000EVB + nRF52DK)' authors: 'Secure Positioning (ETH Zurich / TU Darmstadt)' venue: securepositioning.ch year: 2022 @@ -149,21 +149,21 @@ lastResearched: 2026-06-14 ## Mechanism -UWB ranging measures distance from the **time-of-flight of sub-nanosecond impulse-radio pulses**, not from received signal strength, which is what makes it ~10 cm accurate and resistant to the amplitude-based relay tricks that defeat RSSI proximity (see the UWB Wayfinder `facts`). IEEE 802.15.4z protects the *integrity* of that measurement with the **STS (Scrambled Timestamp Sequence)**: an AES-keyed pseudo-random pulse sequence the two peers share, which the receiver correlates against to authenticate the arrival time, so an attacker without the key cannot forge or replay a legitimate-looking ranging pulse [`ieee802154z`]. The security claim is therefore about the *timestamp*, not confidentiality — and the research surface is correspondingly physical. +UWB ranging measures distance from the **time-of-flight of sub-nanosecond impulse-radio pulses**, not from received signal strength, which is what makes it ~10 cm accurate and resistant to the amplitude-based relay tricks that defeat RSSI proximity (see the UWB Wayfinder `facts`). IEEE 802.15.4z protects the *integrity* of that measurement with the **STS (Scrambled Timestamp Sequence)**: an AES-keyed pseudo-random pulse sequence the two peers share, which the receiver correlates against to authenticate the arrival time, so an attacker without the key cannot forge or replay a legitimate-looking ranging pulse [`ieee802154z`]. The security claim is therefore about the *timestamp*, not confidentiality, and the research surface is correspondingly physical. -The decisive observation in the literature is that the attacker does **not need the STS key** to bias the measurement. The receiver estimates a leading edge / time-of-arrival from accumulated pulse energy; if an adversary injects energy that the estimator commits to *before* the genuine first path, the measured time-of-flight — and hence the distance — shortens [`singh2021secanalysis`]. **Ghost Peak** is the landmark practical result: the first over-the-air distance-reduction attack on HRP 802.15.4z, reducing a 12 m true distance to a reported 0 m against Apple U1 interoperating with NXP and Qorvo chips, with **no cryptographic material** and a ~$65 off-the-shelf device (a DWM3000EVB driven by an nRF52DK), at roughly a **4% per-attempt success rate** [`leu2022ghostpeak`, `ghostpeakproject`]. The earlier security analysis of HRP names the injection families — **Cicada++** and **Adaptive Injection** — and shows that, depending on how the receiver trades miss-detection against performance, the success probability of distance shortening ranges from about **7% to over 90%** [`singh2021secanalysis`]. +The decisive observation in the literature is that the attacker does **not need the STS key** to bias the measurement. The receiver estimates a leading edge / time-of-arrival from accumulated pulse energy; if an adversary injects energy that the estimator commits to *before* the genuine first path, the measured time-of-flight, and hence the distance, shortens [`singh2021secanalysis`]. **Ghost Peak** is the landmark practical result: the first over-the-air distance-reduction attack on HRP 802.15.4z, reducing a 12 m true distance to a reported 0 m against Apple U1 interoperating with NXP and Qorvo chips, with **no cryptographic material** and a ~$65 off-the-shelf device (a DWM3000EVB driven by an nRF52DK), at roughly a **4% per-attempt success rate** [`leu2022ghostpeak`, `ghostpeakproject`]. The earlier security analysis of HRP names the injection families, **Cicada++** and **Adaptive Injection**, and shows that, depending on how the receiver trades miss-detection against performance, the success probability of distance shortening ranges from about **7% to over 90%** [`singh2021secanalysis`]. -The complementary primitive is **distance enlargement**: delaying or annihilating the genuine pulse so the receiver reports a *longer* distance, which matters because a scheme that fails open on lost or implausible ranging can be pushed off the secure path, and because enlargement can mask a relay. UWB-ED frames the detection side — interleaving pulses of different phases and empty pulse slots so an adversary has only ~50% chance of annihilating a given pulse [`singh2019uwbed`]. Finally, **relay and jamming** bound the picture from the other end: because the ranging round is short and latency-constrained, an attacker who cannot *reduce* distance may still **block** it — UWBAD selectively and quickly blocks ranging sessions on COTS Apple/NXP/Qorvo chips by exploiting the normalized cross-correlation in the receiver — turning the assessment into "what does the consumer do when ranging is manipulated or denied?" [`yang2024uwbad`]. +The complementary primitive is **distance enlargement**: delaying or annihilating the genuine pulse so the receiver reports a *longer* distance, which matters because a scheme that fails open on lost or implausible ranging can be pushed off the secure path, and because enlargement can mask a relay. UWB-ED frames the detection side, interleaving pulses of different phases and empty pulse slots so an adversary has only ~50% chance of annihilating a given pulse [`singh2019uwbed`]. Finally, **relay and jamming** bound the picture from the other end: because the ranging round is short and latency-constrained, an attacker who cannot *reduce* distance may still **block** it, UWBAD selectively and quickly blocks ranging sessions on COTS Apple/NXP/Qorvo chips by exploiting the normalized cross-correlation in the receiver, turning the assessment into "what does the consumer do when ranging is manipulated or denied?" [`yang2024uwbad`]. -The ~4% (Ghost Peak) and 7%–90% (Singh et al.) success-probability figures are the papers' own evaluations against specific chip/receiver configurations; they vary with chip, firmware revision, channel and STS length, so treat them as representative of the attack class, not a guarantee against any given product — check current advisories. +The ~4% (Ghost Peak) and 7% to 90% (Singh et al.) success-probability figures are the papers' own evaluations against specific chip/receiver configurations; they vary with chip, firmware revision, channel and STS length, so treat them as representative of the attack class, not a guarantee against any given product, check current advisories. -There is **no open, turnkey distance-reduction exploit**. Ghost Peak and the injection variants use custom DW3000 firmware and bespoke RF engineering that are not released as a runnable product (the Ghost Peak project page gates the code, and the Wayfinder AT note states this explicitly). The procedure below characterises and stress-tests ranging behaviour on a programmable peer — it is not a packaged Ghost-Peak binary, and reproducing a full reduction is research-grade work. +There is **no open, turnkey distance-reduction exploit**. Ghost Peak and the injection variants use custom DW3000 firmware and bespoke RF engineering that are not released as a runnable product (the Ghost Peak project page gates the code, and the Wayfinder AT note states this explicitly). The procedure below characterises and stress-tests ranging behaviour on a programmable peer, it is not a packaged Ghost-Peak binary, and reproducing a full reduction is research-grade work. ## Procedure > Authorised testing only: use your own devices/vehicle or an explicit test target, operate inside an RF-shielded enclosure, and keep the UWB transmitter on the regulator-permitted channels and power. Distance manipulation against a system you do not own is out of scope. -1. **Identify the scheme and PHY before touching the air** (Wayfinder IG step). Confirm silicon (DW3000 / NXP Trimension / Apple U1-U2 — only 802.15.4z parts have STS), HRP vs LRP, the channel (5 or 9), and the application scheme (Apple Nearby Interaction / CCC Digital Key / FiRa). UWB cannot be blind-scanned, so these parameters are mandatory inputs to every later step. +1. **Identify the scheme and PHY before touching the air** (Wayfinder IG step). Confirm silicon (DW3000 / NXP Trimension / Apple U1-U2, only 802.15.4z parts have STS), HRP vs LRP, the channel (5 or 9), and the application scheme (Apple Nearby Interaction / CCC Digital Key / FiRa). UWB cannot be blind-scanned, so these parameters are mandatory inputs to every later step. ```text Example target profile (record before testing): silicon : Qorvo DW3110 (DW3000 family, 802.15.4z, STS supported) @@ -175,13 +175,13 @@ There is **no open, turnkey distance-reduction exploit**. Ghost Peak and the inj 2. **Establish a known-good ranging baseline** with a controllable DW3000 peer, so you can measure manipulation as a deviation from truth. Bring up two boards at a tape-measured separation and log the reported distance. ```bash - # foldedtoad/dwm3000 — DWS3000 shield under Zephyr, two-way ranging example + # foldedtoad/dwm3000, DWS3000 shield under Zephyr, two-way ranging example git clone https://github.com/foldedtoad/dwm3000 west build -b nrf52840dk_nrf52840 dwm3000/examples/ex_05a_ds_twr_init west flash # on the responder board, build/flash ex_05b_ds_twr_resp ``` - Expected: the initiator's serial log prints a per-round distance that tracks the physical separation to ~10 cm (e.g. `DIST: 2.03 m` at a 2.00 m tape measurement). A baseline that does *not* track truth means the PHY config is wrong — fix it before any attack step. + Expected: the initiator's serial log prints a per-round distance that tracks the physical separation to ~10 cm (e.g. `DIST: 2.03 m` at a 2.00 m tape measurement). A baseline that does *not* track truth means the PHY config is wrong, fix it before any attack step. 3. **Capture the live ranging round passively** to confirm the frame format, STS mode and timing you must match. Drive the SEEMOO sniffer into Wireshark. ```bash @@ -190,9 +190,9 @@ There is **no open, turnkey distance-reduction exploit**. Ghost Peak and the inj # flash the EVB firmware per the repo, then pipe to Wireshark: python3 sensniff.py -d /dev/ttyACM0 | wireshark -k -i - ``` - Expected: 802.15.4z frames with the DW3000's 15.65 ps timestamp resolution, showing the ranging-round structure (poll / response / final) of the scheme. Malformed frames are forwarded too — read the dissector output critically. This captures frames you can already decode; it does **not** break the STS. + Expected: 802.15.4z frames with the DW3000's 15.65 ps timestamp resolution, showing the ranging-round structure (poll / response / final) of the scheme. Malformed frames are forwarded too, read the dissector output critically. This captures frames you can already decode; it does **not** break the STS. -4. **Stress-test the ToA / leading-edge estimator** for an early-detection bias — the resilience question. Using the programmable peer, inject pulse energy ahead of the genuine first path (Cicada++/adaptive style) and watch whether the responder's reported distance drops below the true separation. This is the engineered, research-grade step; record the *rate* of any shortening, not a single lucky frame. +4. **Stress-test the ToA / leading-edge estimator** for an early-detection bias, the resilience question. Using the programmable peer, inject pulse energy ahead of the genuine first path (Cicada++/adaptive style) and watch whether the responder's reported distance drops below the true separation. This is the engineered, research-grade step; record the *rate* of any shortening, not a single lucky frame. ```text Observation to record per N rounds: true distance (tape) : 12.00 m @@ -207,18 +207,18 @@ There is **no open, turnkey distance-reduction exploit**. Ghost Peak and the inj ## Field case -Representative worked example (no measured author field data — values to be filled by the tester, marked `[FILL: …]`; do not treat the placeholders as findings): +Representative worked example (no measured author field data, values to be filled by the tester, marked `[FILL: …]`; do not treat the placeholders as findings): -A CCC Digital Key bench rig was set up under authorisation in an RF-shielded room: a Qorvo DWM3000EVB acting as the "vehicle anchor" (responder) and a second DWM3000EVB + nRF52DK as the "key" (initiator), both HRP channel 5, STS mode 1, configured from the BLE bootstrap parameters recovered at the IG step. Step 2 baselined the rig — at a tape-measured **12.00 m** the initiator logged `DIST: 11.9x m`, tracking truth to ~10 cm, confirming a valid ranging link before any attack. +A CCC Digital Key bench rig was set up under authorisation in an RF-shielded room: a Qorvo DWM3000EVB acting as the "vehicle anchor" (responder) and a second DWM3000EVB + nRF52DK as the "key" (initiator), both HRP channel 5, STS mode 1, configured from the BLE bootstrap parameters recovered at the IG step. Step 2 baselined the rig, at a tape-measured **12.00 m** the initiator logged `DIST: 11.9x m`, tracking truth to ~10 cm, confirming a valid ranging link before any attack. -A third programmable DW3000 peer was then introduced as the attacker and driven to inject pulse energy ahead of the genuine first path (Step 4). Across **N = [FILL: number of rounds]** ranging rounds, the responder reported a minimum distance of **[FILL: measured min, m]** with a shortened-round fraction of **[FILL: shortened/N]**. This is the place to be honest about effort: Ghost Peak's published platform — the *same* class of hardware used here (a ~$65 DWM3000EVB + nRF52DK) — achieved 12 m → 0 m at only ~4% per attempt with custom firmware [`leu2022ghostpeak`, `ghostpeakproject`], so a bench reproduction that shows *any* consistent sub-truth report is already a meaningful resilience finding; a null result across a large N is itself the finding (this configuration resisted the primitive). The application-gate test (Step 6) then recorded whether the rig's "unlock" logic would trip on a `[FILL: reduced | blocked]` measurement: **[FILL: unlocked | refused | fell back to BLE]**. +A third programmable DW3000 peer was then introduced as the attacker and driven to inject pulse energy ahead of the genuine first path (Step 4). Across **N = [FILL: number of rounds]** ranging rounds, the responder reported a minimum distance of **[FILL: measured min, m]** with a shortened-round fraction of **[FILL: shortened/N]**. This is the place to be honest about effort: Ghost Peak's published platform, the *same* class of hardware used here (a ~$65 DWM3000EVB + nRF52DK), achieved 12 m → 0 m at only ~4% per attempt with custom firmware [`leu2022ghostpeak`, `ghostpeakproject`], so a bench reproduction that shows *any* consistent sub-truth report is already a meaningful resilience finding; a null result across a large N is itself the finding (this configuration resisted the primitive). The application-gate test (Step 6) then recorded whether the rig's "unlock" logic would trip on a `[FILL: reduced | blocked]` measurement: **[FILL: unlocked | refused | fell back to BLE]**. > Note: no author-measured UWB distance-manipulation field data exists yet for this control; every `[FILL: …]` above is an unmeasured placeholder, not a result. The numeric reduction figures cited (12 m → 0 m, ~4%) are Ghost Peak's, not a local reproduction. ## Remediation -**Developer (silicon / receiver firmware).** Use an STS-protected 802.15.4z HRP (or LRP) part and a receiver design that resists early-detection injection — the published analyses show the receiver's ToA/leading-edge estimator, not the STS secret, is what gets attacked, and that configuration choices move the success rate across an order of magnitude [`singh2021secanalysis`, `leu2022ghostpeak`]. Prefer longer STS, validate the first-path against the STS accumulation rather than raw energy, and adopt enlargement/annihilation-resistant designs (phase-interleaved pulses, empty slots) so injection and cancellation are detectable [`singh2019uwbed`]. Treat DW1000-generation legacy parts (no STS) as non-secure for ranging. +**Developer (silicon / receiver firmware).** Use an STS-protected 802.15.4z HRP (or LRP) part and a receiver design that resists early-detection injection, the published analyses show the receiver's ToA/leading-edge estimator, not the STS secret, is what gets attacked, and that configuration choices move the success rate across an order of magnitude [`singh2021secanalysis`, `leu2022ghostpeak`]. Prefer longer STS, validate the first-path against the STS accumulation rather than raw energy, and adopt enlargement/annihilation-resistant designs (phase-interleaved pulses, empty slots) so injection and cancellation are detectable [`singh2019uwbed`]. Treat DW1000-generation legacy parts (no STS) as non-secure for ranging. -**Integrator (the consuming system).** Require an **STS-authenticated secure** measurement before any gate decision — never accept a legacy or non-secure ranging result for a security-critical action. Bound the acceptable distance tightly, reject physically implausible jumps between rounds, and require multiple consistent secure measurements rather than a single round (this directly counters a probabilistic, ~4%-per-attempt reduction). Bind the UWB session to its BLE/NFC bootstrap so a ranging result cannot be accepted out of session context. +**Integrator (the consuming system).** Require an **STS-authenticated secure** measurement before any gate decision, never accept a legacy or non-secure ranging result for a security-critical action. Bound the acceptable distance tightly, reject physically implausible jumps between rounds, and require multiple consistent secure measurements rather than a single round (this directly counters a probabilistic, ~4%-per-attempt reduction). Bind the UWB session to its BLE/NFC bootstrap so a ranging result cannot be accepted out of session context. -**Operator (deployment).** Configure the system to **fail safe** when ranging is lost, blocked or implausible — a jamming or distance-manipulation attempt must not default to unlocked/approved, and fallback to a weaker proximity signal (BLE RSSI) must not silently bypass the UWB gate [`yang2024uwbad`]. Keep firmware current against vendor advisories; the attack corpus here is representative of the class and dates quickly, so re-check NXP/Qorvo/Apple and OEM advisories rather than treating any single result as the last word. +**Operator (deployment).** Configure the system to **fail safe** when ranging is lost, blocked or implausible, a jamming or distance-manipulation attempt must not default to unlocked/approved, and fallback to a weaker proximity signal (BLE RSSI) must not silently bypass the UWB gate [`yang2024uwbad`]. Keep firmware current against vendor advisories; the attack corpus here is representative of the class and dates quickly, so re-check NXP/Qorvo/Apple and OEM advisories rather than treating any single result as the last word. diff --git a/src/content/controls/rfsam-uwb-phy-01.md b/src/content/controls/rfsam-uwb-phy-01.md index f92490c..aecefb8 100644 --- a/src/content/controls/rfsam-uwb-phy-01.md +++ b/src/content/controls/rfsam-uwb-phy-01.md @@ -11,14 +11,14 @@ applicability: deferred: false objective: >- Determine whether a target's UWB ranging exchange can be captured and - characterised off the air with a real DW3000-class transceiver — recovering the + characterised off the air with a real DW3000-class transceiver, recovering the 802.15.4z frames and their PHY parameters (channel, preamble code, PRF, data - rate, STS mode) — without claiming to break the STS or recover any key. + rate, STS mode), without claiming to break the STS or recover any key. intro: >- Impulse-radio UWB cannot be seen on a normal SDR waterfall or blind-scanned: a UWB channel is >500 MHz wide, sits above 6 GHz, and the signal is sub-nanosecond pulses near the noise floor. Capture is done by a DW3000-class transceiver that - despreads the pulses and frames the 802.15.4z packet in silicon — but only once + despreads the pulses and frames the 802.15.4z packet in silicon, but only once you already know the link's PHY parameters. This control verifies that capture is feasible and what it does (and does not) reveal; it is the prerequisite for the physical-layer distance-manipulation work assessed at the Attack layer. @@ -30,7 +30,7 @@ prerequisites: - 'SEEMOO uwb-sniffer firmware + sensniff host script + Wireshark (open capture path)' - 'or the foldedtoad/dwm3000 (dwt_uwb_driver) port to run/log known two-way-ranging exchanges' signal: - freq: 'HRP UWB ~3.1–10.6 GHz; in practice channel 5 (6489.6 MHz) or channel 9 (7987.2 MHz), each >500 MHz wide' + freq: 'HRP UWB ~3.1 to 10.6 GHz; in practice channel 5 (6489.6 MHz) or channel 9 (7987.2 MHz), each >500 MHz wide' bandwidth: '>500 MHz per channel (cannot be covered by a HackRF/bladeRF/USRP-B210 class SDR)' modulation: 'Impulse radio (sub-nanosecond pulses), HRP 802.15.4z, ~64/124.8 MHz PRF (BPRF/HPRF); 850 kbps / 6.81 Mbps; distance from pulse time-of-flight, not RSSI' skill: advanced @@ -41,7 +41,7 @@ attacks: - leu2022arxiv impact: >- Reduces the measured ranging distance (12 m to 0 m, ~4% per-attempt success) - without any cryptographic material — enough to defeat a proximity gate such + without any cryptographic material, enough to defeat a proximity gate such as CCC Digital Key car entry if no other check stands behind it. preconditions: >- HRP 802.15.4z ranging the attacker can observe and engage; a programmable @@ -49,7 +49,7 @@ attacks: summary: >- The landmark public physical-layer distance-reduction attack on HRP UWB (Apple U1 inter-operating with NXP/Qorvo). It motivates why characterising - the captured ranging waveform and round structure matters — though the attack + the captured ranging waveform and round structure matters, though the attack itself is engineered against the radio, not packaged as a turnkey tool. - name: Mix-Down clock manipulation refs: @@ -62,7 +62,7 @@ attacks: the standard's reliance on clock behaviour, not a single implementation. summary: >- Shows that even STS-authenticated ranging is manipulable at the physical layer - via clock effects — reinforcing that capture/characterisation, not key recovery, + via clock effects, reinforcing that capture/characterisation, not key recovery, is the UWB research surface. references: - key: leu2022ghostpeak @@ -93,14 +93,14 @@ references: url: 'https://standards.ieee.org/ieee/802.15.4z/10230/' type: standard - key: seemoo-uwb-sniffer - title: 'SEEMOO uwb-sniffer — a UWB sniffer with accurate timestamps' + title: 'SEEMOO uwb-sniffer: a UWB sniffer with accurate timestamps' authors: 'SEEMOO Lab, TU Darmstadt' venue: GitHub year: 2022 url: 'https://github.com/seemoo-lab/uwb-sniffer' type: tool - key: foldedtoad-dwm3000 - title: 'foldedtoad/dwm3000 — port of Qorvo/Decawave DWM3000 driver to the DWS3000 Arduino shield' + title: 'foldedtoad/dwm3000: port of Qorvo/Decawave DWM3000 driver to the DWS3000 Arduino shield' authors: 'C. Callender (foldedtoad)' venue: GitHub year: 2024 @@ -124,9 +124,9 @@ lastResearched: 2026-06-14 HRP UWB is impulse radio: the transmitter emits very short (sub-nanosecond) RF pulses spread across roughly 500 MHz of bandwidth (the 802.15.4z HRP channels occupy ~499.2 MHz), intermittently and at very low power spectral density, on channel 5 (6489.6 MHz) or channel 9 (7987.2 MHz) [ieee802154z2020]. Distance is derived from the pulses' time-of-flight, not from signal strength; the 802.15.4z amendment's stated purpose is to "increase the integrity and accuracy of ranging measurements," which is what makes the ranging hard to spoof [ieee802154z2020]. The wide-bandwidth impulse timing yields centimetre-level precision (commonly cited as ~10 cm in line-of-sight). None of this is observable on a commodity SDR: those radios top out near 6 GHz and offer tens of MHz of instantaneous bandwidth, so a UWB channel sits both above their frequency ceiling and far wider than their capture bandwidth, and there is no turnkey software receiver for the impulse waveform. -Capture is therefore done by a real DW3000-class transceiver. The chip despreads the incoming pulses against the known channel and preamble code (and, for secure ranging, correlates the Scrambled Timestamp Sequence) and frames the 802.15.4z packet in hardware [seemoo-uwb-sniffer]. The consequence is that PHY and framing happen together on the radio: you do not stare at I/Q, you drive a transceiver that already knows the link. That makes the *Identify* homework mandatory — channel, preamble code, PRF, data rate and STS mode/length must be set in advance, because UWB cannot be blind-scanned [seemoo-uwb-sniffer]. +Capture is therefore done by a real DW3000-class transceiver. The chip despreads the incoming pulses against the known channel and preamble code (and, for secure ranging, correlates the Scrambled Timestamp Sequence) and frames the 802.15.4z packet in hardware [seemoo-uwb-sniffer]. The consequence is that PHY and framing happen together on the radio: you do not stare at I/Q, you drive a transceiver that already knows the link. That makes the *Identify* homework mandatory, channel, preamble code, PRF, data rate and STS mode/length must be set in advance, because UWB cannot be blind-scanned [seemoo-uwb-sniffer]. -The STS is an AES-keyed pseudo-random pulse sequence the two ranging peers share; the receiver only trusts an arrival time it can authenticate against the expected STS [ieee802154z2020]. So capturing the over-the-air frames does **not** break the STS or recover a key — it recovers the frames and their structure that you are already entitled to decode [seemoo-uwb-sniffer]. The genuine UWB research surface is physical: whether the time-of-flight measurement can be reduced at the physical layer without the key. The landmark public result, **Ghost Peak**, is a practical HRP UWB distance-reduction attack (Apple U1 inter-operating with NXP/Qorvo) that cut 12 m to 0 m with ~4% per-attempt success, using a ~$65 off-the-shelf DWM3000EVB driven by an nRF52DK and **no cryptographic material** [leu2022ghostpeak][leu2022arxiv]. The **Mix-Down** clock-manipulation work later showed 10 m reduced to 0 m on commercial 802.15.4z chips by exploiting transceiver clock imperfections [anliker2023timeforchange]. Both are assessed at the RFSAM *Attack* layer; this PHY control verifies the capture-and-characterise prerequisite they rely on, and confirms what that capture reveals. +The STS is an AES-keyed pseudo-random pulse sequence the two ranging peers share; the receiver only trusts an arrival time it can authenticate against the expected STS [ieee802154z2020]. So capturing the over-the-air frames does **not** break the STS or recover a key, it recovers the frames and their structure that you are already entitled to decode [seemoo-uwb-sniffer]. The genuine UWB research surface is physical: whether the time-of-flight measurement can be reduced at the physical layer without the key. The landmark public result, **Ghost Peak**, is a practical HRP UWB distance-reduction attack (Apple U1 inter-operating with NXP/Qorvo) that cut 12 m to 0 m with ~4% per-attempt success, using a ~$65 off-the-shelf DWM3000EVB driven by an nRF52DK and **no cryptographic material** [leu2022ghostpeak][leu2022arxiv]. The **Mix-Down** clock-manipulation work later showed 10 m reduced to 0 m on commercial 802.15.4z chips by exploiting transceiver clock imperfections [anliker2023timeforchange]. Both are assessed at the RFSAM *Attack* layer; this PHY control verifies the capture-and-characterise prerequisite they rely on, and confirms what that capture reveals. ## Procedure @@ -142,7 +142,7 @@ All steps are observational capture on your own equipment or with explicit autho Expected: two benign post-build errors (`arm-none-eabi-size: ... file format not recognized`) that the README documents as non-issues; the firmware otherwise builds clean. 3. **Set the link's PHY parameters in firmware.** Edit the `config` struct in `uwb_sniffer.c` to the channel, preamble code, data rate, STS mode and STS length recovered in step 1, then re-flash [seemoo-uwb-sniffer]. - Expected: an incorrect configuration yields long, malformed frames where STS or preamble bits are misread as data — that mismatch is itself the signal that a parameter is wrong. + Expected: an incorrect configuration yields long, malformed frames where STS or preamble bits are misread as data, that mismatch is itself the signal that a parameter is wrong. 4. **Stream the frames to Wireshark over the sensniff pipe.** The firmware speaks the sensniff protocol and adds reception timestamps at the DW3000's 15.65 ps accuracy [seemoo-uwb-sniffer]. ``` @@ -159,24 +159,24 @@ All steps are observational capture on your own equipment or with explicit autho ```bash git clone https://github.com/foldedtoad/dwm3000 ``` - Expected: a known TWR exchange you can log end-to-end. This captures only the exchanges your peer participates in — it is a development driver, not a passive sniffer for arbitrary third-party links. + Expected: a known TWR exchange you can log end-to-end. This captures only the exchanges your peer participates in, it is a development driver, not a passive sniffer for arbitrary third-party links. 6. **Characterise and record.** From the captured frames, document channel/preamble/PRF/data-rate/STS mode, the frame format, and the ranging-round structure (TWR/TDoA/PDoA) for the scheme in use. This is the deliverable: the capture is feasible and characterised; it does not assert any STS break. ## Field case -Illustrative walkthrough — substitute the values you capture on your own bench. A representative, reproducible bring-up against a DW3000 development link you own (no third-party device required): +Illustrative walkthrough, substitute the values you capture on your own bench. A representative, reproducible bring-up against a DW3000 development link you own (no third-party device required): -- Flash the SEEMOO sniffer firmware to a DWM3000EVB on a NUCLEO-F429ZI; in a second board run a foldedtoad/dwm3000 TWR example as the controllable peer. Configure both to the same parameters — the shipped default config (`config_options.c`, `CONFIG_OPTION_01`) is **channel 5 (6489.6 MHz), preamble code 9, 64 MHz PRF, 850 kbps**, with STS mode 1 / STS length 64 as set by the example [foldedtoad-dwm3000]. +- Flash the SEEMOO sniffer firmware to a DWM3000EVB on a NUCLEO-F429ZI; in a second board run a foldedtoad/dwm3000 TWR example as the controllable peer. Configure both to the same parameters, the shipped default config (`config_options.c`, `CONFIG_OPTION_01`) is **channel 5 (6489.6 MHz), preamble code 9, 64 MHz PRF, 850 kbps**, with STS mode 1 / STS length 64 as set by the example [foldedtoad-dwm3000]. - Start capture with `python3 sensniff.py -DINFO` and attach Wireshark to the `/tmp/sensniff` pipe. -- Result: the TWR poll / response / final frames appear in Wireshark with 15.65 ps reception timestamps; deliberately changing the sniffer's preamble code away from the peer's produces the malformed long frames the README warns about — a clean demonstration that UWB capture is parameter-locked, not scanned. +- Result: the TWR poll / response / final frames appear in Wireshark with 15.65 ps reception timestamps; deliberately changing the sniffer's preamble code away from the peer's produces the malformed long frames the README warns about, a clean demonstration that UWB capture is parameter-locked, not scanned. -This is an illustrative bring-up, not measured author field data: the end-to-end capture was not bench-run for this control, so the asserted result (the TWR frame list and 15.65 ps timestamps) is still to be recorded on hardware: [FILL: bench-captured frame list, timestamps, and the working `config` struct values]. The configuration values are the real shipped default — channel 5, preamble code 9, 64 MHz PRF, 850 kbps, STS mode 1 / length 64 — confirmed against `CONFIG_OPTION_01` in foldedtoad/dwm3000 `config_options.c`, not invented. +This is an illustrative bring-up, not measured author field data: the end-to-end capture was not bench-run for this control, so the asserted result (the TWR frame list and 15.65 ps timestamps) is still to be recorded on hardware: [FILL: bench-captured frame list, timestamps, and the working `config` struct values]. The configuration values are the real shipped default, channel 5, preamble code 9, 64 MHz PRF, 850 kbps, STS mode 1 / length 64, confirmed against `CONFIG_OPTION_01` in foldedtoad/dwm3000 `config_options.c`, not invented. ## Remediation UWB ranging capture is observational, so remediation targets the consumers of the ranging result, not the radio that hears it. - **Developers (chip/stack):** require STS-authenticated, secure-ranging measurements and reject legacy/non-secure 802.15.4a or non-STS ranging where the application is security-sensitive; the STS is what keeps a captured frame from being a forgeable distance claim [ieee802154z2020]. Track the physical-layer distance-reduction literature (Ghost Peak, Mix-Down) as an open class against HRP, not a single patchable bug [leu2022ghostpeak][anliker2023timeforchange]. -- **Integrators (product):** never let a single UWB proximity measurement be the only thing standing between an attacker and the asset. Bound the acceptable distance tightly, reject implausible distance jumps, and fail safe if ranging is lost or inconsistent — because the proven attacks shorten distance at the physical layer without any key [leu2022ghostpeak]. Protect the BLE/NFC bootstrap that keys the UWB session (assessed in the BLE and RFID/NFC wayfinders), since the session keys live there, not in the pulses. -- **Operators (deployment):** treat UWB-gated access (car entry/start, locks, payment proximity) as defence-in-depth — pair it with an independent factor and monitor for anomalous unlock/range patterns. Recognise that an adversary capturing and characterising the link is the precursor step, not yet a compromise. +- **Integrators (product):** never let a single UWB proximity measurement be the only thing standing between an attacker and the asset. Bound the acceptable distance tightly, reject implausible distance jumps, and fail safe if ranging is lost or inconsistent, because the proven attacks shorten distance at the physical layer without any key [leu2022ghostpeak]. Protect the BLE/NFC bootstrap that keys the UWB session (assessed in the BLE and RFID/NFC wayfinders), since the session keys live there, not in the pulses. +- **Operators (deployment):** treat UWB-gated access (car entry/start, locks, payment proximity) as defence-in-depth, pair it with an independent factor and monitor for anomalous unlock/range patterns. Recognise that an adversary capturing and characterising the link is the precursor step, not yet a compromise. diff --git a/src/content/controls/rfsam-wifi-cr-01.md b/src/content/controls/rfsam-wifi-cr-01.md index f9b90c8..e3e062c 100644 --- a/src/content/controls/rfsam-wifi-cr-01.md +++ b/src/content/controls/rfsam-wifi-cr-01.md @@ -11,8 +11,8 @@ applicability: - WPS deferred: false objective: >- - Determine whether a network's pre-shared key can be recovered offline — from a - captured 4-way handshake or a clientless RSN PMKID — or whether an enabled WPS + Determine whether a network's pre-shared key can be recovered offline, from a + captured 4-way handshake or a clientless RSN PMKID, or whether an enabled WPS PIN gives a faster online path to the PSK; and whether a WPA3 deployment is actually exposed to a WPA2 downgrade. intro: >- @@ -20,7 +20,7 @@ intro: >- either the 4-way handshake or, since 2018, the RSN PMKID straight from the access point with no client present. WPS PIN and WPA3 transitional mode add further recovery paths. This control captures the relevant material and assesses - key-recovery feasibility — perform every active step only against networks you + key-recovery feasibility, perform every active step only against networks you are explicitly authorised to test. prerequisites: hardware: @@ -29,7 +29,7 @@ prerequisites: software: - 'hcxdumptool (PMKID / EAPOL capture), hcxtools (pcapng → hc22000 conversion), hashcat (offline crack), aircrack-ng (capture + CPU crack), reaver / pixiewps (WPS PIN and Pixie-Dust).' signal: - freq: '2.4 GHz (2.400–2.4835 GHz) · 5 GHz (UNII, ~5.15–5.85 GHz) · 6 GHz (5.925–7.125 GHz, Wi-Fi 6E/7)' + freq: '2.4 GHz (2.400 to 2.4835 GHz) · 5 GHz (UNII, ~5.15 to 5.85 GHz) · 6 GHz (5.925 to 7.125 GHz, Wi-Fi 6E/7)' bandwidth: '20/40/80/160 MHz channels (320 MHz in Wi-Fi 7)' modulation: 'OFDM (802.11a/g/n/ac/ax/be) / DSSS (legacy 802.11b)' skill: intermediate @@ -38,7 +38,7 @@ attacks: refs: - steube2018pmkid impact: >- - Recovers the material needed to crack the PSK offline from the AP alone — no + Recovers the material needed to crack the PSK offline from the AP alone, no associated client and no deauthentication required. preconditions: >- An AP whose first EAPOL/RSN frame carries a PMKID (many WPA2-PSK APs do); @@ -108,7 +108,7 @@ attacks: preconditions: An unpatched client (or AP) that reinstalls an already-installed key during the handshake. summary: >- Replaying handshake message 3 forces the victim to reinstall the PTK, - resetting the nonce/replay counter and enabling decryption of traffic — + resetting the nonce/replay counter and enabling decryption of traffic, independent of passphrase strength. - name: Kr00k cve: @@ -169,7 +169,7 @@ references: url: 'https://nvd.nist.gov/vuln/detail/CVE-2019-9494' type: cve - key: cve-2019-15126 - title: 'CVE-2019-15126: Kr00k — all-zero-key encryption of buffered frames' + title: 'CVE-2019-15126: Kr00k: all-zero-key encryption of buffered frames' venue: NVD year: 2019 url: 'https://nvd.nist.gov/vuln/detail/CVE-2019-15126' @@ -189,17 +189,17 @@ lastResearched: 2026-06-14 --- ## Mechanism -WPA2-Personal authenticates with a Pre-Shared Key: both sides derive a Pairwise Master Key (PMK) from the passphrase and run an EAPOL **4-way handshake** to prove possession and derive session keys. Anyone who captures that handshake holds enough PMK-derived material to test passphrase guesses offline — so WPA2-PSK confidentiality reduces to passphrase strength, not to anything that happens on the air. +WPA2-Personal authenticates with a Pre-Shared Key: both sides derive a Pairwise Master Key (PMK) from the passphrase and run an EAPOL **4-way handshake** to prove possession and derive session keys. Anyone who captures that handshake holds enough PMK-derived material to test passphrase guesses offline, so WPA2-PSK confidentiality reduces to passphrase strength, not to anything that happens on the air. -Since 2018 the auditor often does not even need a client. The AP's first EAPOL frame can carry an **RSN PMKID**, computed as `HMAC-SHA1-128(PMK, "PMK Name" | MAC_AP | MAC_STA)` [steube2018pmkid]. Because the PMKID is a function of the PMK and the two MAC addresses, capturing it from the AP alone — no associated station, no deauthentication noise — yields the same offline-crackable target as a full handshake [steube2018pmkid]. Both paths converge on hashcat's unified WPA hash mode 22000 (the PMKID attack originally landed as mode 16800) [steube2018pmkid]. +Since 2018 the auditor often does not even need a client. The AP's first EAPOL frame can carry an **RSN PMKID**, computed as `HMAC-SHA1-128(PMK, "PMK Name" | MAC_AP | MAC_STA)` [steube2018pmkid]. Because the PMKID is a function of the PMK and the two MAC addresses, capturing it from the AP alone, no associated station, no deauthentication noise, yields the same offline-crackable target as a full handshake [steube2018pmkid]. Both paths converge on hashcat's unified WPA hash mode 22000 (the PMKID attack originally landed as mode 16800) [steube2018pmkid]. -**WPS** is a parallel weakness that sidesteps the passphrase entirely. The 8-digit PIN is validated in two halves with the last digit a checksum, and the AP's response reveals which half is wrong — collapsing brute force from 10^8 to roughly 11,000 attempts where the AP applies no lockout [viehbock2011wps]. Worse, the **Pixie-Dust** attack recovers the PIN *offline* from a single exchange on chipsets whose Registrar generates the E-S1/E-S2 nonces with weak or zero entropy (Ralink nonces fixed at zero; weak Broadcom PRNG) [bongard2014pixie]. A recovered PIN yields the PSK directly, regardless of passphrase strength. +**WPS** is a parallel weakness that sidesteps the passphrase entirely. The 8-digit PIN is validated in two halves with the last digit a checksum, and the AP's response reveals which half is wrong, collapsing brute force from 10^8 to roughly 11,000 attempts where the AP applies no lockout [viehbock2011wps]. Worse, the **Pixie-Dust** attack recovers the PIN *offline* from a single exchange on chipsets whose Registrar generates the E-S1/E-S2 nonces with weak or zero entropy (Ralink nonces fixed at zero; weak Broadcom PRNG) [bongard2014pixie]. A recovered PIN yields the PSK directly, regardless of passphrase strength. -**WPA3-SAE** is designed to resist offline dictionary attacks — the Dragonfly handshake never exposes a passphrase-derived hash to a passive observer. **Dragonblood** showed this is not the whole story: SAE implementations in hostapd/wpa_supplicant leaked password information through timing and cache side-channels, and the protocol permits group-downgrade and transition-mode downgrade [vanhoef2020dragonblood][cve-2019-9494]. A WPA3 network running **transitional (mixed) mode** still advertises WPA2-PSK to legacy clients, so the WPA2 capture-and-crack surface above remains fully available. This control's WPA3 step is therefore mainly a check for transitional mode and management-frame protection, not an offline crack of SAE itself. +**WPA3-SAE** is designed to resist offline dictionary attacks, the Dragonfly handshake never exposes a passphrase-derived hash to a passive observer. **Dragonblood** showed this is not the whole story: SAE implementations in hostapd/wpa_supplicant leaked password information through timing and cache side-channels, and the protocol permits group-downgrade and transition-mode downgrade [vanhoef2020dragonblood][cve-2019-9494]. A WPA3 network running **transitional (mixed) mode** still advertises WPA2-PSK to legacy clients, so the WPA2 capture-and-crack surface above remains fully available. This control's WPA3 step is therefore mainly a check for transitional mode and management-frame protection, not an offline crack of SAE itself. Two confidentiality breaks recover *plaintext* without recovering the PSK, and are worth noting when scoping: **KRACK** forces reinstallation of the PTK during the handshake, resetting the nonce/replay counter and enabling decryption on unpatched endpoints [vanhoef2017krack][cve-2017-13077]; **Kr00k** causes affected Broadcom/Cypress chips to encrypt frames buffered across a disassociation with an all-zero key [cve-2019-15126]. Both are implementation/patch-state findings rather than passphrase-strength findings. -This corpus is representative, not exhaustive — Wi-Fi attack surface and patch state move quickly, so check current vendor advisories for the specific chipset and firmware. +This corpus is representative, not exhaustive, Wi-Fi attack surface and patch state move quickly, so check current vendor advisories for the specific chipset and firmware. ## Procedure @@ -237,7 +237,7 @@ This corpus is representative, not exhaustive — Wi-Fi attack surface and patch hashcat -m 22000 target.hc22000 wordlist.txt # or aircrack-ng -w wordlist.txt -b hs-01.cap (CPU, handshake only) ``` - A `Status: Cracked` line with the recovered passphrase means the PSK is weak. Exhausting a reasonable wordlist/mask without a hit is itself a finding — the passphrase resisted the tested effort. + A `Status: Cracked` line with the recovered passphrase means the PSK is weak. Exhausting a reasonable wordlist/mask without a hit is itself a finding, the passphrase resisted the tested effort. 6. **Where WPS is enabled, test the PIN paths.** Pixie-Dust first (offline, near-instant on vulnerable chipsets), then a rate-limited online PIN attempt only if Pixie-Dust fails and the AP has no lockout. ```bash @@ -245,19 +245,19 @@ This corpus is representative, not exhaustive — Wi-Fi attack surface and patch ``` On success reaver prints the recovered `WPS PIN` and the `WPA PSK`. A returned PSK here means the network is compromised regardless of passphrase length. -7. **For a network advertising WPA3, do not attempt an offline SAE crack — assess exposure instead.** Confirm whether it runs transitional (mixed WPA2/WPA3) mode and whether PMF is required, since transitional mode re-exposes the WPA2 paths above. +7. **For a network advertising WPA3, do not attempt an offline SAE crack, assess exposure instead.** Confirm whether it runs transitional (mixed WPA2/WPA3) mode and whether PMF is required, since transitional mode re-exposes the WPA2 paths above. ```bash sudo airodump-ng --bssid -c wlan0mon ``` - In the `AUTH` field, `SAE` alone with `MFP required` indicates WPA3-only; `PSK SAE` (or a parallel WPA2 BSSID/IE) indicates transitional mode — record it as downgrade exposure rather than a crackable finding. + In the `AUTH` field, `SAE` alone with `MFP required` indicates WPA3-only; `PSK SAE` (or a parallel WPA2 BSSID/IE) indicates transitional mode, record it as downgrade exposure rather than a crackable finding. ## Field case -Illustrative walkthrough — substitute the values you capture. This is a representative example of the two key-recovery paths against an authorised WPA2-PSK test AP (a consumer router in an RF-isolated lab, test passphrase, no production clients), not a logged engagement; treat the steps as the expected shape of the result and fill in the placeholders with your own measurements. +Illustrative walkthrough, substitute the values you capture. This is a representative example of the two key-recovery paths against an authorised WPA2-PSK test AP (a consumer router in an RF-isolated lab, test passphrase, no production clients), not a logged engagement; treat the steps as the expected shape of the result and fill in the placeholders with your own measurements. -A clientless PMKID grab in step 2 produces a PMKID for the target BSSID shortly after `hcxdumptool` starts — no client need ever associate and no deauth is sent. `hcxpcapngtool -o target.hc22000 pmkid.pcapng` writes a single PMKID hash. Running `hashcat -m 22000 target.hc22000 rockyou.txt` recovers the lab passphrase, confirming the offline path end to end. +A clientless PMKID grab in step 2 produces a PMKID for the target BSSID shortly after `hcxdumptool` starts, no client need ever associate and no deauth is sent. `hcxpcapngtool -o target.hc22000 pmkid.pcapng` writes a single PMKID hash. Running `hashcat -m 22000 target.hc22000 rockyou.txt` recovers the lab passphrase, confirming the offline path end to end. -Where the same AP has WPS left enabled (the factory default on many consumer models), `reaver -i wlan0mon -b -c -K 1 -vv` completes the Pixie-Dust attack and returns the WPS PIN and the WPA PSK directly — the passphrase length is irrelevant once the PIN falls. +Where the same AP has WPS left enabled (the factory default on many consumer models), `reaver -i wlan0mon -b -c -K 1 -vv` completes the Pixie-Dust attack and returns the WPS PIN and the WPA PSK directly, the passphrase length is irrelevant once the PIN falls. The numbers below are placeholders for whoever runs this against a real target; do not treat them as measured. @@ -269,6 +269,6 @@ The numbers below are placeholders for whoever runs this against a real target; **Developer / vendor.** Ship WPS PIN disabled by default, or remove the external-Registrar PIN method entirely; where it must exist, use a CSPRNG for the E-S1/E-S2 nonces and enforce a hard lockout after a few failed attempts to close the Pixie-Dust and two-half brute-force classes [bongard2014pixie][viehbock2011wps]. Patch SAE implementations against the Dragonblood side-channels (constant-time hash-to-curve; hostapd/wpa_supplicant > 2.7) [vanhoef2020dragonblood][cve-2019-9494], and ship the KRACK and Kr00k fixes in client and AP firmware [vanhoef2017krack][cve-2019-15126]. -**Integrator.** Provision a long, high-entropy passphrase (random, not a memorable phrase) so the offline PMKID/handshake crack is computationally infeasible — this is the single most effective control for WPA2-PSK. Disable WPS entirely. Where the threat model warrants it, move sensitive networks to WPA2/WPA3-Enterprise (802.1X/EAP) so there is no shared offline-crackable secret at all. +**Integrator.** Provision a long, high-entropy passphrase (random, not a memorable phrase) so the offline PMKID/handshake crack is computationally infeasible, this is the single most effective control for WPA2-PSK. Disable WPS entirely. Where the threat model warrants it, move sensitive networks to WPA2/WPA3-Enterprise (802.1X/EAP) so there is no shared offline-crackable secret at all. -**Operator.** Deploy WPA3-SAE in **non-transitional** mode with Protected Management Frames (PMF/802.11w) required — this removes the WPA2 downgrade surface and blunts the deauth used to force handshakes. Keep AP and client firmware current against KRACK/Kr00k/FragAttacks-class advisories, and re-survey periodically: treat the tool and CVE corpus above as representative and check current advisories for your specific hardware. +**Operator.** Deploy WPA3-SAE in **non-transitional** mode with Protected Management Frames (PMF/802.11w) required, this removes the WPA2 downgrade surface and blunts the deauth used to force handshakes. Keep AP and client firmware current against KRACK/Kr00k/FragAttacks-class advisories, and re-survey periodically: treat the tool and CVE corpus above as representative and check current advisories for your specific hardware. diff --git a/src/content/controls/rfsam-wifi-ll-01.md b/src/content/controls/rfsam-wifi-ll-01.md index 0bac041..1d56896 100644 --- a/src/content/controls/rfsam-wifi-ll-01.md +++ b/src/content/controls/rfsam-wifi-ll-01.md @@ -11,7 +11,7 @@ deferred: false objective: >- Determine, from a passive monitor-mode capture, whether the network protects its 802.11 management frames (802.11w / PMF) and how much device identity the - beacons, probe requests and association frames leak in the clear — establishing + beacons, probe requests and association frames leak in the clear, establishing exposure to deauthentication DoS, handshake-forcing and evil-twin targeting. intro: >- 802.11 management frames (beacons, probe request/response, association and @@ -27,16 +27,16 @@ prerequisites: software: - 'aircrack-ng (airodump-ng), Kismet or hcxdumptool for capture; Wireshark/tshark for decode' signal: - freq: '2.4 GHz (2.400–2.4835 GHz) · 5 GHz (UNII, ~5.15–5.85 GHz) · 6 GHz (5.925–7.125 GHz, Wi-Fi 6E/7)' + freq: '2.4 GHz (2.400 to 2.4835 GHz) · 5 GHz (UNII, ~5.15 to 5.85 GHz) · 6 GHz (5.925 to 7.125 GHz, Wi-Fi 6E/7)' bandwidth: '20/40/80/160 MHz channels (320 MHz in Wi-Fi 7)' - modulation: 'OFDM (a/g/n/ac/ax/be) / DSSS (legacy b) — demodulated on the adapter chipset' + modulation: 'OFDM (a/g/n/ac/ax/be) / DSSS (legacy b), demodulated on the adapter chipset' skill: intermediate attacks: - name: Deauthentication / disassociation DoS refs: - bellardo2003dos impact: >- - Forged deauth/disassoc frames evict one or all clients on demand — a denial + Forged deauth/disassoc frames evict one or all clients on demand, a denial of service, and the lever that forces a fresh 4-way handshake for offline cracking under RFSAM-WIFI-CR-01. preconditions: Management Frame Protection (802.11w / PMF) absent or not enforced on the BSS. @@ -68,7 +68,7 @@ attacks: probe requests let devices be tracked even when the MAC address is randomized. references: - key: ieee80211w2009 - title: 'IEEE 802.11w-2009 — Amendment 4: Protected Management Frames' + title: 'IEEE 802.11w-2009: Amendment 4: Protected Management Frames' authors: IEEE venue: IEEE Standards Association year: 2009 @@ -96,14 +96,14 @@ references: url: 'https://papers.mathyvanhoef.com/asiaccs2016.pdf' type: paper - key: mcdougall2022probing - title: 'Probing for Passwords — Privacy Implications of SSIDs in Probe Requests' + title: 'Probing for Passwords: Privacy Implications of SSIDs in Probe Requests' authors: 'J. Ansohn McDougall, C. Burkert, D. Demmler, M. Schwarz, V. Hubbe, H. Federrath' venue: 'ACNS 2022 (arXiv:2206.03745)' year: 2022 url: 'https://arxiv.org/abs/2206.03745' type: paper - key: wireshark-wpa-induction - title: "wpa-Induction.pcap — Wireshark SampleCaptures wiki (Wifi / Wireless LAN captures / 802.11)" + title: "wpa-Induction.pcap: Wireshark SampleCaptures wiki (Wifi / Wireless LAN captures / 802.11)" authors: Wireshark project venue: Wireshark SampleCaptures wiki url: 'https://gitlab.com/wireshark/wireshark/-/wikis/SampleCaptures' @@ -125,15 +125,15 @@ lastResearched: 2026-06-14 --- ## Mechanism -802.11 separates management, control and data frames. Beacons, probe request/response, and association/authentication frames are sent in the clear, and — critically — by default they carry no cryptographic authentication, so a receiver cannot tell a genuine frame from a forged one. The 802.11w-2009 amendment ("Protected Management Frames", PMF) was published specifically to close this: it adds integrity, origin authentication and replay protection to a subset of management frames, principally deauthentication, disassociation and robust action frames [ieee80211w2009]. By design the amendment cannot protect beacons or probe request/response frames, since those are exchanged before any security association exists [ieee80211w2009]. So even with PMF fully enforced, the *discovery* frames still leak; PMF only stops the *forged-deauth* class. +802.11 separates management, control and data frames. Beacons, probe request/response, and association/authentication frames are sent in the clear, and, critically, by default they carry no cryptographic authentication, so a receiver cannot tell a genuine frame from a forged one. The 802.11w-2009 amendment ("Protected Management Frames", PMF) was published specifically to close this: it adds integrity, origin authentication and replay protection to a subset of management frames, principally deauthentication, disassociation and robust action frames [ieee80211w2009]. By design the amendment cannot protect beacons or probe request/response frames, since those are exchanged before any security association exists [ieee80211w2009]. So even with PMF fully enforced, the *discovery* frames still leak; PMF only stops the *forged-deauth* class. Where PMF is absent or not enforced, the canonical consequence is the deauthentication/disassociation denial-of-service: an attacker spoofs the AP or client MAC and transmits a single forged deauth frame to evict a station, repeatedly to deny service, or tactically to force a client to reconnect and emit a fresh 4-way handshake. Bellardo and Savage documented this management-frame DoS class in 2003 and noted that, unlike the confidentiality flaws of the era, these availability attacks need no key and target the protocol's own management plane [bellardo2003dos]. The forced-reconnect variant is the lever that feeds the handshake-capture path assessed under RFSAM-WIFI-CR-01. -The second exposure is identity. A client doing *active* scanning broadcasts directed probe requests naming SSIDs it has joined before — its Preferred Network List. Cunche, Kaafar and Boreli showed in 2012 that these lists fingerprint a device and even let social links between owners be inferred from overlapping network histories [cunche2012linking]. MAC-address randomization was meant to blunt this, but Vanhoef et al. demonstrated in 2016 that probe-request information elements, scrambler seeds and sequence numbers fingerprint and track devices despite randomized MACs, correctly following a sizable fraction of devices for tens of minutes [vanhoef2016randomization]. More recently, McDougall et al. found users frequently type sensitive strings — including passwords and email addresses — into SSID fields, which then leak verbatim in probe requests [mcdougall2022probing]. Together these make management-frame capture both a tracking surface and the reconnaissance that seeds evil-twin (AP-impersonation) targeting, executed under the Wi-Fi Attack layer. +The second exposure is identity. A client doing *active* scanning broadcasts directed probe requests naming SSIDs it has joined before, its Preferred Network List. Cunche, Kaafar and Boreli showed in 2012 that these lists fingerprint a device and even let social links between owners be inferred from overlapping network histories [cunche2012linking]. MAC-address randomization was meant to blunt this, but Vanhoef et al. demonstrated in 2016 that probe-request information elements, scrambler seeds and sequence numbers fingerprint and track devices despite randomized MACs, correctly following a sizable fraction of devices for tens of minutes [vanhoef2016randomization]. More recently, McDougall et al. found users frequently type sensitive strings, including passwords and email addresses, into SSID fields, which then leak verbatim in probe requests [mcdougall2022probing]. Together these make management-frame capture both a tracking surface and the reconnaissance that seeds evil-twin (AP-impersonation) targeting, executed under the Wi-Fi Attack layer. ## Procedure -All capture below is **passive** and non-transmitting. Steps 1–4 observe only. The active deauth check in step 5 transmits and must be run **only on equipment you own or are explicitly authorised to test**, ideally in an RF-shielded enclosure; classic deauth is a real denial of service against bystanders. The active execution properly belongs to the Wi-Fi Attack layer — here it is a one-shot confirmation of the exposure read in step 4. +All capture below is **passive** and non-transmitting. Steps 1 to 4 observe only. The active deauth check in step 5 transmits and must be run **only on equipment you own or are explicitly authorised to test**, ideally in an RF-shielded enclosure; classic deauth is a real denial of service against bystanders. The active execution properly belongs to the Wi-Fi Attack layer, here it is a one-shot confirmation of the exposure read in step 4. 1. Put the adapter into monitor mode and park it on the target's channel (RFSAM-RES-11): ```bash @@ -154,41 +154,41 @@ All capture below is **passive** and non-transmitting. Steps 1–4 observe only. -T fields -e wlan.ssid \ -e wlan.rsn.capabilities.mfpr -e wlan.rsn.capabilities.mfpc ``` - `mfpr=1` (MFP Required) means PMF is enforced — deauth DoS is blocked. `mfpc=1, mfpr=0` means capable but optional. Both `0` (or no RSN IE at all, i.e. Open/WEP) means management frames are unprotected. + `mfpr=1` (MFP Required) means PMF is enforced, deauth DoS is blocked. `mfpc=1, mfpr=0` means capable but optional. Both `0` (or no RSN IE at all, i.e. Open/WEP) means management frames are unprotected. -4. Inventory the identity leakage — broadcast SSIDs and the probe-request history of nearby clients (their PNLs): +4. Inventory the identity leakage, broadcast SSIDs and the probe-request history of nearby clients (their PNLs): ```bash tshark -r wifi-ll-01.cap -Y "wlan.fc.type_subtype == 0x04 && wlan.ssid != \"\"" \ -T fields -e wlan.sa -e wlan.ssid | sort -u ``` - Each line is a client MAC and an SSID it is actively seeking — the data the tracking and evil-twin work in [cunche2012linking] and [vanhoef2016randomization] consumes. Note any SSID strings that look like credentials [mcdougall2022probing]. + Each line is a client MAC and an SSID it is actively seeking, the data the tracking and evil-twin work in [cunche2012linking] and [vanhoef2016randomization] consumes. Note any SSID strings that look like credentials [mcdougall2022probing]. 5. **(Authorised scope only)** If step 3 showed PMF absent, confirm deauth susceptibility against your own test client with a single, bounded burst, then stop: ```bash sudo aireplay-ng --deauth 1 -a AA:BB:CC:DD:EE:FF -c 11:22:33:44:55:66 wlan0mon ``` - `--deauth 1` sends one round (not a flood). The test client disassociating confirms the exposure; airodump-ng on the same channel should then show the renewed association (and, if a client reconnects, an EAPOL handshake — the input to RFSAM-WIFI-CR-01). Against a PMF-enforced BSS the client stays connected. + `--deauth 1` sends one round (not a flood). The test client disassociating confirms the exposure; airodump-ng on the same channel should then show the renewed association (and, if a client reconnects, an EAPOL handshake, the input to RFSAM-WIFI-CR-01). Against a PMF-enforced BSS the client stays connected. ## Field case -Steps 3–4 are demonstrated below against a documented public sample so the read-out can be reproduced exactly; the step-5 active confirmation is left as an illustrative lab walk-through, where every unmeasured datum is marked `[FILL: …]` and must not be cited as a real finding. +Steps 3 to 4 are demonstrated below against a documented public sample so the read-out can be reproduced exactly; the step-5 active confirmation is left as an illustrative lab walk-through, where every unmeasured datum is marked `[FILL: …]` and must not be cited as a real finding. -Worked against the public Wireshark sample capture `wpa-Induction.pcap` (Wireshark SampleCaptures wiki, "Wifi / Wireless LAN captures / 802.11") [wireshark-wpa-induction] — a passive 802.11 trace, not a live engagement of our own: +Worked against the public Wireshark sample capture `wpa-Induction.pcap` (Wireshark SampleCaptures wiki, "Wifi / Wireless LAN captures / 802.11") [wireshark-wpa-induction], a passive 802.11 trace, not a live engagement of our own: -- Step 3 on its WPA2-PSK beacon for SSID `Coherer` (BSSID `00:0c:41:82:b2:55`, AKM = PSK) returns `RSN Capabilities 0x0000` — `mfpr=0, mfpc=0`, PMF neither required nor capable — so management frames are unprotected and an associated client stays deauth-susceptible [wireshark-wpa-induction]. +- Step 3 on its WPA2-PSK beacon for SSID `Coherer` (BSSID `00:0c:41:82:b2:55`, AKM = PSK) returns `RSN Capabilities 0x0000`, `mfpr=0, mfpc=0`, PMF neither required nor capable, so management frames are unprotected and an associated client stays deauth-susceptible [wireshark-wpa-induction]. - Step 4 over the same capture inventoried `2` distinct client MACs emitting directed probe requests (`00:0d:93:82:36:3a` probing `Coherer`, `00:0f:66:16:94:73` probing `linksys`) and `2` distinct probed SSIDs, of which `none observed` resembled credentials or email addresses [wireshark-wpa-induction]. -For the active confirmation, an illustrative lab walk-through against a consumer AP on channel 6 with an ALFA AWUS036ACH — substitute the values you capture: +For the active confirmation, an illustrative lab walk-through against a consumer AP on channel 6 with an ALFA AWUS036ACH, substitute the values you capture: - Step 4 over a `[FILL: N]`-minute capture in a `[FILL: location type, e.g. office lobby]` would inventory the live PNLs of nearby clients. - Step 5, on the operator's own test laptop, a single `aireplay-ng --deauth 1` round dropped the client and airodump-ng captured the renewed EAPOL handshake within `[FILL: seconds]`. -An Electronic Cats Minino (ESP32-C6) reproduces steps 1–4 standalone on 2.4 GHz, writing the capture to microSD and logging the survey geographically over its onboard GPS for the wardriving variant — useful where a laptop is impractical, with the caveat that it sees only 2.4 GHz management/handshake frames, not 5/6 GHz traffic. A WiFi Pineapple consumes the same step-4 PNL inventory to seed an evil-twin clone, but that is an Attack-layer action outside this control's scope and must be separately authorised. +An Electronic Cats Minino (ESP32-C6) reproduces steps 1 to 4 standalone on 2.4 GHz, writing the capture to microSD and logging the survey geographically over its onboard GPS for the wardriving variant, useful where a laptop is impractical, with the caveat that it sees only 2.4 GHz management/handshake frames, not 5/6 GHz traffic. A WiFi Pineapple consumes the same step-4 PNL inventory to seed an evil-twin clone, but that is an Attack-layer action outside this control's scope and must be separately authorised. ## Remediation -**Developer (client/STA firmware and OS):** Implement MAC-address randomization *and* minimize probe-request fingerprintability — randomize sequence numbers and avoid distinctive information-element ordering, since randomized MACs alone do not prevent tracking [vanhoef2016randomization]. Prefer passive scanning (listen for beacons) over directed active probing so the Preferred Network List is not broadcast [cunche2012linking]; never echo user-entered SSID strings that could carry secrets [mcdougall2022probing]. +**Developer (client/STA firmware and OS):** Implement MAC-address randomization *and* minimize probe-request fingerprintability, randomize sequence numbers and avoid distinctive information-element ordering, since randomized MACs alone do not prevent tracking [vanhoef2016randomization]. Prefer passive scanning (listen for beacons) over directed active probing so the Preferred Network List is not broadcast [cunche2012linking]; never echo user-entered SSID strings that could carry secrets [mcdougall2022probing]. -**Integrator (AP / network design):** Enable 802.11w with **MFP Required** (`mfpr=1`), not merely capable, on every BSS — this authenticates deauth/disassoc frames and defeats the forged-deauth DoS and handshake-forcing class [ieee80211w2009] [bellardo2003dos]. PMF is mandatory under WPA3 and on 6 GHz; enforce it on WPA2 too. Note that PMF does not protect beacons or probe frames, so identity leakage must be addressed at the client [ieee80211w2009]. +**Integrator (AP / network design):** Enable 802.11w with **MFP Required** (`mfpr=1`), not merely capable, on every BSS, this authenticates deauth/disassoc frames and defeats the forged-deauth DoS and handshake-forcing class [ieee80211w2009] [bellardo2003dos]. PMF is mandatory under WPA3 and on 6 GHz; enforce it on WPA2 too. Note that PMF does not protect beacons or probe frames, so identity leakage must be addressed at the client [ieee80211w2009]. -**Operator (deployment/policy):** Audit beacons for `mfpr` enforcement across the estate; treat any PMF-optional BSS as deauth-exposed. On managed clients, disable auto-join for sensitive SSIDs and clear stale saved networks to shrink the leaked PNL. Avoid hidden SSIDs as a security measure — they force clients to actively probe the hidden name, worsening the leakage this control measures rather than reducing it. +**Operator (deployment/policy):** Audit beacons for `mfpr` enforcement across the estate; treat any PMF-optional BSS as deauth-exposed. On managed clients, disable auto-join for sensitive SSIDs and clear stale saved networks to shrink the leaked PNL. Avoid hidden SSIDs as a security measure, they force clients to actively probe the hidden name, worsening the leakage this control measures rather than reducing it. diff --git a/src/content/controls/rfsam-wifi-sp-01.md b/src/content/controls/rfsam-wifi-sp-01.md index 85ed495..4d304fa 100644 --- a/src/content/controls/rfsam-wifi-sp-01.md +++ b/src/content/controls/rfsam-wifi-sp-01.md @@ -13,7 +13,7 @@ objective: >- Establish which 802.11 bands and channels carry traffic in scope, enumerate the access points and clients on each, and confirm whether the auditing radio can passively capture (and, where later controls require it, inject) on every - band the targets use — so a later "not seen" is recorded as a capability gap, + band the targets use, so a later "not seen" is recorded as a capability gap, not an all-clear. intro: >- Wi-Fi spans three bands and dozens of channels, and a radio listens to only @@ -24,76 +24,76 @@ intro: >- before any active step. prerequisites: hardware: - - 'A monitor-mode-capable 802.11 adapter — ALFA AWUS036ACH (RTL8812AU) for 2.4/5 GHz with injection; a Wi-Fi 6E adapter for 6 GHz; or an Electronic Cats Minino (ESP32-C6) for standalone 2.4 GHz survey/wardriving with onboard GPS.' + - 'A monitor-mode-capable 802.11 adapter, ALFA AWUS036ACH (RTL8812AU) for 2.4/5 GHz with injection; a Wi-Fi 6E adapter for 6 GHz; or an Electronic Cats Minino (ESP32-C6) for standalone 2.4 GHz survey/wardriving with onboard GPS.' software: - 'Linux with mac80211 drivers; airmon-ng / airodump-ng (aircrack-ng), Kismet, hcxdumptool, and Wireshark for inspection.' signal: - freq: '2.400–2.4835 GHz (2.4 GHz) · ~5.15–5.85 GHz (5 GHz U-NII) · 5.925–7.125 GHz (6 GHz, Wi-Fi 6E/7)' + freq: '2.400 to 2.4835 GHz (2.4 GHz) · ~5.15 to 5.85 GHz (5 GHz U-NII) · 5.925 to 7.125 GHz (6 GHz, Wi-Fi 6E/7)' bandwidth: '20 / 40 / 80 / 160 MHz channels (320 MHz in Wi-Fi 7)' modulation: 'DSSS (legacy 2.4 GHz) and OFDM / OFDMA (802.11a/g/n/ac/ax); QAM subcarriers up to 1024-QAM (ax) / 4096-QAM (be)' skill: beginner attacks: [] references: - key: ieee80211-2020 - title: 'IEEE Std 802.11-2020 — Wireless LAN Medium Access Control (MAC) and Physical Layer (PHY) Specifications' + title: 'IEEE Std 802.11-2020: Wireless LAN Medium Access Control (MAC) and Physical Layer (PHY) Specifications' authors: IEEE 802.11 Working Group venue: IEEE Standards Association year: 2021 url: 'https://standards.ieee.org/ieee/802.11/7028/' type: standard - key: radiotap - title: 'Radiotap — the de facto standard header for 802.11 frame injection and reception' + title: 'Radiotap: the de facto standard header for 802.11 frame injection and reception' authors: D. Young et al. venue: radiotap.org url: 'https://www.radiotap.org/' type: spec - key: wireshark-wlan - title: 'CaptureSetup/WLAN — capturing 802.11 traffic and enabling monitor mode' + title: 'CaptureSetup/WLAN: capturing 802.11 traffic and enabling monitor mode' venue: Wireshark Wiki url: 'https://wiki.wireshark.org/CaptureSetup/WLAN' type: spec - key: linux-dfs - title: 'DFS (Dynamic Frequency Selection) — Channel Availability Check and radar detection in mac80211/cfg80211' + title: 'DFS (Dynamic Frequency Selection): Channel Availability Check and radar detection in mac80211/cfg80211' venue: Linux Wireless (kernel.org) documentation url: 'https://wireless.docs.kernel.org/en/latest/en/developers/dfs.html' type: spec - key: fcc-6ghz-2020 - title: 'Unlicensed Use of the 6 GHz Band (5.925–7.125 GHz) — FCC Report and Order fact sheet' + title: 'Unlicensed Use of the 6 GHz Band (5.925 to 7.125 GHz): FCC Report and Order fact sheet' authors: Federal Communications Commission venue: FCC year: 2020 url: 'https://docs.fcc.gov/public/attachments/doc-363490a1.pdf' type: standard - key: kismet - title: 'Kismet — passive wireless sniffer, survey and wardriving tool' + title: 'Kismet: passive wireless sniffer, survey and wardriving tool' authors: M. Kershaw (dragorn) et al. venue: Kismet Wireless url: 'https://github.com/kismetwireless/kismet' type: tool - key: aircrack-ng - title: 'aircrack-ng — 802.11 monitor-mode capture suite (airmon-ng, airodump-ng, aireplay-ng)' + title: 'aircrack-ng: 802.11 monitor-mode capture suite (airmon-ng, airodump-ng, aireplay-ng)' venue: aircrack-ng url: 'https://github.com/aircrack-ng/aircrack-ng' type: tool - key: hcxdumptool - title: 'hcxdumptool — capture packets from WLAN devices (PMKID / EAPOL)' + title: 'hcxdumptool: capture packets from WLAN devices (PMKID / EAPOL)' authors: ZerBea venue: GitHub url: 'https://github.com/ZerBea/hcxdumptool' type: tool - key: minino - title: 'Minino — Electronic Cats ESP32-C6 multiprotocol multitool (Wi-Fi wardriving, sniffer, GPS)' + title: 'Minino: Electronic Cats ESP32-C6 multiprotocol multitool (Wi-Fi wardriving, sniffer, GPS)' authors: Electronic Cats venue: GitHub url: 'https://github.com/ElectronicCats/Minino' type: tool - key: airodump-csv - title: 'aircrack-ng — airgraph-ng sample airodump-ng CSV (scripts/airgraph-ng/test/test-1.txt) and airodump-ng PWR column definition' + title: 'aircrack-ng: airgraph-ng sample airodump-ng CSV (scripts/airgraph-ng/test/test-1.txt) and airodump-ng PWR column definition' venue: aircrack-ng url: 'https://github.com/aircrack-ng/aircrack-ng/blob/master/scripts/airgraph-ng/test/test-1.txt' type: tool - key: wpa3-spec - title: 'WPA3 Specification — 6 GHz band constraints (WPA3/OWE only, PMF mandatory, no transition mode)' + title: 'WPA3 Specification: 6 GHz band constraints (WPA3/OWE only, PMF mandatory, no transition mode)' authors: Wi-Fi Alliance venue: Wi-Fi Alliance url: 'https://www.wi-fi.org/system/files/WPA3%20Specification%20v3.4.pdf' @@ -111,23 +111,23 @@ lastResearched: 2026-06-14 --- ## Mechanism -802.11 operates across three unlicensed bands: 2.4 GHz (2.400–2.4835 GHz), the 5 GHz U-NII bands (~5.15–5.85 GHz), and — since the 2020 FCC order opening 1200 MHz of new spectrum — 6 GHz (5.925–7.125 GHz), used by Wi-Fi 6E and Wi-Fi 7 [fcc-6ghz-2020][ieee80211-2020]. The PHY is DSSS for legacy 2.4 GHz rates and OFDM/OFDMA for 802.11a/g/n/ac/ax, in channels of 20/40/80/160 MHz (320 MHz in Wi-Fi 7) [ieee80211-2020]. A receiver demodulates only the channel it is tuned to, so observing a whole environment means hopping channels and logging what is heard on each — the survey. +802.11 operates across three unlicensed bands: 2.4 GHz (2.400 to 2.4835 GHz), the 5 GHz U-NII bands (~5.15 to 5.85 GHz), and, since the 2020 FCC order opening 1200 MHz of new spectrum, 6 GHz (5.925 to 7.125 GHz), used by Wi-Fi 6E and Wi-Fi 7 [fcc-6ghz-2020][ieee80211-2020]. The PHY is DSSS for legacy 2.4 GHz rates and OFDM/OFDMA for 802.11a/g/n/ac/ax, in channels of 20/40/80/160 MHz (320 MHz in Wi-Fi 7) [ieee80211-2020]. A receiver demodulates only the channel it is tuned to, so observing a whole environment means hopping channels and logging what is heard on each, the survey. -Passive capture depends on **monitor mode**: outside monitor mode an adapter delivers only unicast traffic to/from the host plus broadcast/multicast, often with synthetic Ethernet headers and no radio metadata; in monitor mode the adapter's frame filter is switched off and every received 802.11 frame — management, control and data — is delivered to userspace with a radio-layer header [wireshark-wlan]. That per-frame metadata (channel, rate, signal) is carried in a **radiotap** header prepended to each captured frame, the de facto standard for 802.11 reception and injection across Linux drivers and libpcap [radiotap]. Whether a given adapter supports monitor mode, and on which bands, is a property of its chipset and driver — not every adapter does it, and many built-in cards cannot inject at all [wireshark-wlan]. +Passive capture depends on **monitor mode**: outside monitor mode an adapter delivers only unicast traffic to/from the host plus broadcast/multicast, often with synthetic Ethernet headers and no radio metadata; in monitor mode the adapter's frame filter is switched off and every received 802.11 frame, management, control and data, is delivered to userspace with a radio-layer header [wireshark-wlan]. That per-frame metadata (channel, rate, signal) is carried in a **radiotap** header prepended to each captured frame, the de facto standard for 802.11 reception and injection across Linux drivers and libpcap [radiotap]. Whether a given adapter supports monitor mode, and on which bands, is a property of its chipset and driver, not every adapter does it, and many built-in cards cannot inject at all [wireshark-wlan]. -Two band-specific constraints scope what a survey can see. **DFS (Dynamic Frequency Selection):** many 5 GHz channels are shared with radar; before a master transmits on a DFS channel it must perform a Channel Availability Check, sitting idle and listening for radar pulses, and must vacate on detection [linux-dfs]. A passive survey can still *receive* on DFS channels, but APs may be sparse or absent there, and an injection-capable adapter will refuse to transmit until CAC completes — relevant to later active controls. **6 GHz:** Wi-Fi 6E/7 traffic is invisible to a 2.4/5 GHz-only adapter; capturing it requires a 6 GHz-capable radio [fcc-6ghz-2020]. Recording these gaps is the point of this control: it sets the honest scope so a later "no handshake / no AP seen" is read as a capability limit, not a clean result. +Two band-specific constraints scope what a survey can see. **DFS (Dynamic Frequency Selection):** many 5 GHz channels are shared with radar; before a master transmits on a DFS channel it must perform a Channel Availability Check, sitting idle and listening for radar pulses, and must vacate on detection [linux-dfs]. A passive survey can still *receive* on DFS channels, but APs may be sparse or absent there, and an injection-capable adapter will refuse to transmit until CAC completes, relevant to later active controls. **6 GHz:** Wi-Fi 6E/7 traffic is invisible to a 2.4/5 GHz-only adapter; capturing it requires a 6 GHz-capable radio [fcc-6ghz-2020]. Recording these gaps is the point of this control: it sets the honest scope so a later "no handshake / no AP seen" is read as a capability limit, not a clean result. -This is an observational, capture-feasibility control — the map drawn before any AT-layer step (deauthentication, rogue AP) is attempted. It carries no offensive technique of its own, hence no `attacks[]`. +This is an observational, capture-feasibility control, the map drawn before any AT-layer step (deauthentication, rogue AP) is attempted. It carries no offensive technique of its own, hence no `attacks[]`. ## Procedure -> Authorised-testing framing: even a "passive" survey can capture other parties' frames and (with GPS) their locations. Run it only within an authorised scope, against networks you own or are permitted to assess, and store captures as sensitive evidence. Steps 2–6 here transmit nothing; the deauth/injection check in step 5 is an active transmission and must stay inside that authorisation. +> Authorised-testing framing: even a "passive" survey can capture other parties' frames and (with GPS) their locations. Run it only within an authorised scope, against networks you own or are permitted to assess, and store captures as sensitive evidence. Steps 2 to 6 here transmit nothing; the deauth/injection check in step 5 is an active transmission and must stay inside that authorisation. 1. **Identify the adapter and its bands.** Confirm the chipset and which bands the driver exposes: ```bash iw list | grep -A40 'Band' ``` - Each `Band N:` block lists the frequencies/channels the radio can tune. Note whether 5 GHz and/or 6 GHz bands appear at all — absence here is a hard capability gap [wireshark-wlan]. + Each `Band N:` block lists the frequencies/channels the radio can tune. Note whether 5 GHz and/or 6 GHz bands appear at all, absence here is a hard capability gap [wireshark-wlan]. 2. **Enter monitor mode.** Put the interface into monitor mode and kill processes that would fight it: ```bash @@ -152,24 +152,24 @@ This is an observational, capture-feasibility control — the map drawn before a ```bash sudo aireplay-ng --test wlan0mon ``` - `Injection is working!` confirms transmit capability; a failure means later "no handshake captured" results would be your radio, not the target [aircrack-ng]. This step transmits — keep it inside the authorised scope. + `Injection is working!` confirms transmit capability; a failure means later "no handshake captured" results would be your radio, not the target [aircrack-ng]. This step transmits, keep it inside the authorised scope. -6. **Record DFS / 6 GHz gaps.** Note any 5 GHz DFS channels where the survey saw no traffic (an AP may be present but the radio cannot be confirmed there without CAC) [linux-dfs], and explicitly record whether 6 GHz was surveyed at all — a 2.4/5 GHz adapter cannot see Wi-Fi 6E/7 [fcc-6ghz-2020]. Optionally confirm key-material capture feasibility with a clientless PMKID probe (`hcxdumptool`) on in-scope APs, written as pcapng for the CR-layer control [hcxdumptool]. +6. **Record DFS / 6 GHz gaps.** Note any 5 GHz DFS channels where the survey saw no traffic (an AP may be present but the radio cannot be confirmed there without CAC) [linux-dfs], and explicitly record whether 6 GHz was surveyed at all, a 2.4/5 GHz adapter cannot see Wi-Fi 6E/7 [fcc-6ghz-2020]. Optionally confirm key-material capture feasibility with a clientless PMKID probe (`hcxdumptool`) on in-scope APs, written as pcapng for the CR-layer control [hcxdumptool]. ## Field case -Illustrative walkthrough — substitute the values you capture. Surveying a small-office network in scope, an ALFA AWUS036ACH (RTL8812AU) in monitor mode is hopped across 2.4 and 5 GHz with `airodump-ng --band abg`. A typical 2.4 GHz pass finds the target SSID on channel 6 (WPA2-PSK/CCMP) plus two neighbour APs on 1 and 11; the 5 GHz pass finds the same ESSID's `ac` BSSID on channel 36 (non-DFS). `aireplay-ng --test wlan0mon` returning `Injection is working!` on channel 6 is what scopes the later handshake-capture control as feasible on 2.4 GHz. +Illustrative walkthrough, substitute the values you capture. Surveying a small-office network in scope, an ALFA AWUS036ACH (RTL8812AU) in monitor mode is hopped across 2.4 and 5 GHz with `airodump-ng --band abg`. A typical 2.4 GHz pass finds the target SSID on channel 6 (WPA2-PSK/CCMP) plus two neighbour APs on 1 and 11; the 5 GHz pass finds the same ESSID's `ac` BSSID on channel 36 (non-DFS). `aireplay-ng --test wlan0mon` returning `Injection is working!` on channel 6 is what scopes the later handshake-capture control as feasible on 2.4 GHz. The point of the survey is that the two gaps below get recorded, not hidden: -- **6 GHz not surveyed** — the RTL8812AU has no 6 GHz radio, so any Wi-Fi 6E client steering to 6 GHz is invisible. Mark it as a capability gap requiring a Wi-Fi 6E adapter to close [fcc-6ghz-2020]. -- **5 GHz DFS channels (52–144)** — no APs observed there, but a passive sweep cannot distinguish "no AP" from "AP present, not captured" on DFS channels without a longer dwell; record it as `unconfirmed` rather than `clear` [linux-dfs]. +- **6 GHz not surveyed**, the RTL8812AU has no 6 GHz radio, so any Wi-Fi 6E client steering to 6 GHz is invisible. Mark it as a capability gap requiring a Wi-Fi 6E adapter to close [fcc-6ghz-2020]. +- **5 GHz DFS channels (52 to 144)**, no APs observed there, but a passive sweep cannot distinguish "no AP" from "AP present, not captured" on DFS channels without a longer dwell; record it as `unconfirmed` rather than `clear` [linux-dfs]. -Record the measured signal level for each BSSID from the live `airodump-ng` table rather than assuming it. For a documented public reference of that table format, the sample airodump-ng survey CSV shipped with aircrack-ng (aircrack-ng/aircrack-ng, `scripts/airgraph-ng/test/test-1.txt`) carries a `Power` column per BSSID [airodump-csv]: `02:1D:7E:47:F6:B3` (ch 11, WPA2/CCMP/PSK, ESSID `kwifi`) Power 18; `00:13:46:08:87:0E` (ch 6, WPA/TKIP/PSK, `kevinh`) Power 14; `00:16:B6:39:B6:ED` (ch 6, WPA2/CCMP/PSK, `giggity`) Power 14; `00:02:2D:8E:F9:FB` (ch 1, WEP) Power 20; and `02:7A:75:47:0E:87` (ch 11, OPN) Power -1. One caveat when reading any such table: this older capture stores Power as a positive magnitude with `-1` as the no-signal sentinel, whereas the current airodump-ng live-table convention (per its manpage) is negative dBm — strong ≈ -40, average ≈ -55, weak ≈ -70, and `-1` meaning the driver does not report a signal level [airodump-csv]. Read each BSSID's value against whichever convention your build emits, and treat `-1` as "no reading," not "very weak." +Record the measured signal level for each BSSID from the live `airodump-ng` table rather than assuming it. For a documented public reference of that table format, the sample airodump-ng survey CSV shipped with aircrack-ng (aircrack-ng/aircrack-ng, `scripts/airgraph-ng/test/test-1.txt`) carries a `Power` column per BSSID [airodump-csv]: `02:1D:7E:47:F6:B3` (ch 11, WPA2/CCMP/PSK, ESSID `kwifi`) Power 18; `00:13:46:08:87:0E` (ch 6, WPA/TKIP/PSK, `kevinh`) Power 14; `00:16:B6:39:B6:ED` (ch 6, WPA2/CCMP/PSK, `giggity`) Power 14; `00:02:2D:8E:F9:FB` (ch 1, WEP) Power 20; and `02:7A:75:47:0E:87` (ch 11, OPN) Power -1. One caveat when reading any such table: this older capture stores Power as a positive magnitude with `-1` as the no-signal sentinel, whereas the current airodump-ng live-table convention (per its manpage) is negative dBm, strong ≈ -40, average ≈ -55, weak ≈ -70, and `-1` meaning the driver does not report a signal level [airodump-csv]. Read each BSSID's value against whichever convention your build emits, and treat `-1` as "no reading," not "very weak." ## Remediation -This is an auditor-capability baseline rather than a device finding — its "remediation" is twofold: hardening guidance for the defender, and discipline for the auditor. +This is an auditor-capability baseline rather than a device finding, its "remediation" is twofold: hardening guidance for the defender, and discipline for the auditor. -- **Developer / vendor:** Do not rely on a hidden SSID or an unusual channel for security — a passive survey enumerates the BSSID, channel and security mode from beacons regardless [ieee80211-2020][wireshark-wlan]. Set the strongest mutually supported security (WPA3-SAE; WPA2-CCMP at minimum) and enable Protected Management Frames (802.11w) so later AT-layer deauth controls find no easy target. On the 6 GHz band — opened for unlicensed use by the 2020 FCC order [fcc-6ghz-2020] — WPA3 (or OWE) and PMF are mandatory by Wi-Fi Alliance certification, with no WPA2/transition mode permitted [wpa3-spec]. -- **Integrator / operator:** Inventory which bands your estate actually uses and ensure monitoring/IDS covers all of them, including 6 GHz and DFS channels — an attacker steering a client to an unmonitored band exploits the same blind spot this control measures [fcc-6ghz-2020][linux-dfs]. Deploy wireless IDS to flag rogue APs and deauth floods that a survey would otherwise only reveal after the fact. -- **Auditor:** Always confirm and document the adapter's band coverage and injection capability up front (steps 1, 5) so scope is honest; treat every "not seen" on an unsupported band or unconfirmed DFS channel as a capability gap, never an all-clear. Channel corpora and adapter chipset support date quickly — verify current driver/monitor-mode status for your hardware rather than assuming [wireshark-wlan]. +- **Developer / vendor:** Do not rely on a hidden SSID or an unusual channel for security, a passive survey enumerates the BSSID, channel and security mode from beacons regardless [ieee80211-2020][wireshark-wlan]. Set the strongest mutually supported security (WPA3-SAE; WPA2-CCMP at minimum) and enable Protected Management Frames (802.11w) so later AT-layer deauth controls find no easy target. On the 6 GHz band, opened for unlicensed use by the 2020 FCC order [fcc-6ghz-2020], WPA3 (or OWE) and PMF are mandatory by Wi-Fi Alliance certification, with no WPA2/transition mode permitted [wpa3-spec]. +- **Integrator / operator:** Inventory which bands your estate actually uses and ensure monitoring/IDS covers all of them, including 6 GHz and DFS channels, an attacker steering a client to an unmonitored band exploits the same blind spot this control measures [fcc-6ghz-2020][linux-dfs]. Deploy wireless IDS to flag rogue APs and deauth floods that a survey would otherwise only reveal after the fact. +- **Auditor:** Always confirm and document the adapter's band coverage and injection capability up front (steps 1, 5) so scope is honest; treat every "not seen" on an unsupported band or unconfirmed DFS channel as a capability gap, never an all-clear. Channel corpora and adapter chipset support date quickly, verify current driver/monitor-mode status for your hardware rather than assuming [wireshark-wlan]. diff --git a/src/content/controls/rfsam-zigbee-cr-01.md b/src/content/controls/rfsam-zigbee-cr-01.md index 11a1f44..d59dea7 100644 --- a/src/content/controls/rfsam-zigbee-cr-01.md +++ b/src/content/controls/rfsam-zigbee-cr-01.md @@ -9,7 +9,7 @@ applicability: deferred: false objective: >- Determine how a Zigbee network's network key is established, transported to a - joining device, and rotated — specifically whether the Trust Center transports + joining device, and rotated, specifically whether the Trust Center transports the network key under the well-known default link key 'ZigBeeAlliance09' (or in the clear), so that anyone who captured a join can recover it, and whether the key is ever rotated over the device's lifetime. @@ -19,7 +19,7 @@ intro: >- how that key reaches a joining device: a centralized Trust Center sends it in an APS Transport-Key, and if that transport is protected only by the publicly known default Trust Center link key 'ZigBeeAlliance09', anyone who sniffed the join can - recover the key and decrypt — and forge — the entire network. This control checks + recover the key and decrypt, and forge, the entire network. This control checks the join key-transport and whether the key is ever rotated. prerequisites: hardware: @@ -28,7 +28,7 @@ prerequisites: software: - 'A capture path that feeds Wireshark (KillerBee zbdump/zbwireshark, catnip, the nRF 802.15.4 Sniffer extcap, or whsniff), plus KillerBee zbdsniff for network-key extraction and Wireshark for decryption.' signal: - freq: '2.4 GHz ISM (2.405–2.480 GHz), 16 channels (11–26) spaced 5 MHz; sub-GHz 868 MHz (EU) / 902–928 MHz (Americas)' + freq: '2.4 GHz ISM (2.405 to 2.480 GHz), 16 channels (11 to 26) spaced 5 MHz; sub-GHz 868 MHz (EU) / 902 to 928 MHz (Americas)' bandwidth: '2 MHz per channel (2.4 GHz)' modulation: 'IEEE 802.15.4 O-QPSK with DSSS, 250 kbps (2.4 GHz); BPSK/O-QPSK at lower rates sub-GHz' skill: intermediate @@ -40,7 +40,7 @@ attacks: - killerbee impact: >- Recovering the PAN-wide network key decrypts all NWK/APS traffic and lets an - attacker forge frames and issue cluster commands the devices act on — a full + attacker forge frames and issue cluster commands the devices act on, a full break of the network's confidentiality and integrity. preconditions: >- The Trust Center transports the network key under the well-known default link @@ -71,7 +71,7 @@ attacks: key transport for capture. references: - key: zillner2015 - title: 'ZigBee Exploited — The Good, the Bad and the Ugly' + title: 'ZigBee Exploited: The Good, the Bad and the Ugly' authors: Tobias Zillner (Cognosec) venue: Black Hat USA 2015 (whitepaper) year: 2015 @@ -92,7 +92,7 @@ references: url: 'https://csa-iot.org/wp-content/uploads/2023/04/05-3474-23-csg-zigbee-specification-compressed.pdf' type: spec - key: silabs-security - title: 'Zigbee Security — Standard Security (network key, key rotation / Key Switch, install codes)' + title: 'Zigbee Security: Standard Security (network key, key rotation / Key Switch, install codes)' authors: Silicon Labs venue: Silicon Labs Documentation year: 2026 @@ -106,20 +106,20 @@ references: url: 'https://securelist.com/zigbee-protocol-security-assessment/118373/' type: blog - key: killerbee - title: 'KillerBee — IEEE 802.15.4 / ZigBee Security Research Toolkit (zbdump, zbdsniff, zbreplay)' + title: 'KillerBee: IEEE 802.15.4 / ZigBee Security Research Toolkit (zbdump, zbdsniff, zbreplay)' authors: River Loop Security venue: GitHub year: 2023 url: 'https://github.com/riverloopsec/killerbee' type: tool - key: killerbee-control4-sample - title: 'control4-sample.pcap / control4-sample.txt — KillerBee-shipped Control4 OTA network-key delivery capture' + title: 'control4-sample.pcap / control4-sample.txt: KillerBee-shipped Control4 OTA network-key delivery capture' authors: River Loop Security venue: GitHub (riverloopsec/killerbee, sample/) url: 'https://github.com/riverloopsec/killerbee/blob/master/sample/control4-sample.pcap' type: tool - key: secbee - title: 'SecBee — ZigBee security testing tool (built on scapy-radio and KillerBee)' + title: 'SecBee: ZigBee security testing tool (built on scapy-radio and KillerBee)' authors: Cognosec venue: GitHub year: 2016 @@ -148,17 +148,17 @@ lastResearched: 2026-06-14 ## Mechanism -Zigbee secures both the network (NWK) and application-support (APS) layers with AES-128 in CCM* mode, providing encryption plus a message integrity code [csa-zigbee-r23][zillner2015]. There are two key types: a **network key** shared by every device in the PAN, used to secure NWK-layer (notably broadcast) traffic, and **link keys** shared pairwise between two devices and used by the APS sub-layer [zillner2015][csa-zigbee-r23]. Because the network key is PAN-wide, recovering it once decrypts the whole mesh — so this layer is about how that one key is *provisioned, transported and rotated*, not about the strength of AES. +Zigbee secures both the network (NWK) and application-support (APS) layers with AES-128 in CCM* mode, providing encryption plus a message integrity code [csa-zigbee-r23][zillner2015]. There are two key types: a **network key** shared by every device in the PAN, used to secure NWK-layer (notably broadcast) traffic, and **link keys** shared pairwise between two devices and used by the APS sub-layer [zillner2015][csa-zigbee-r23]. Because the network key is PAN-wide, recovering it once decrypts the whole mesh, so this layer is about how that one key is *provisioned, transported and rotated*, not about the strength of AES. **How the key is established and transported.** In a centralized network the coordinator is also the **Trust Center**, the security authority that hands out the network key [silabs-security]. When a device joins, the Trust Center delivers the network key in an **APS Transport-Key** command, which must be protected by a link key so the key is not exposed in plaintext [securelist2025][silabs-security]. The exposure is in *which* link key protects it. The standard defines a global default Trust Center link key, `ZigBeeAlliance09` (hex `5A6967426565416C6C69616E63653039`), included in pre-3.0 Zigbee to ease testing and interoperability [securelist2025][csa-zigbee-r23]. **Why the default-key transport is the classic break.** Zillner (Cognosec, Black Hat USA 2015) showed this is not merely a misconfiguration but a *profile requirement*: the Home Automation Public Application Profile states that "the current network key shall be transported using the default TC link key in the case where the joining device is unknown," and the ZigBee Light Link profile likewise mandates support for an insecure default-key join as a fallback [zillner2015]. Consequently, "if an attacker is able to sniff a device join using the default TC link key, the active network key is compromised and the confidentiality of the whole network communication can be considered as compromised" [zillner2015]. Many vendors left the default key enabled on shipping consumer devices, turning the fallback into the normal case [securelist2025]. KillerBee's `zbdsniff` automates exactly this recovery: it scans a join capture for the Transport-Key and decrypts it under `ZigBeeAlliance09` (or reads it directly when sent in the clear) [killerbee]. Cognosec released the SecBee framework (built on scapy-radio and KillerBee) to automate auditing Zigbee security services for these weaknesses [zillner2015][secbee]. -**Why rejoin matters for key recovery.** If no join is on the air, the Transport-Key can be forced back onto it: making a device leave and rejoin re-runs the key transport [securelist2025]. The rejoin procedure is itself a documented weakness — Wang et al. (RAID 2022) formally verified that Zigbee's Trust-Center rejoin "sacrifices authenticity to achieve" availability, confirming a known design flaw and revealing two new ones, with proof-of-concept attacks ranging from denial of service to device hijacking against real hubs [wang2022rejoin]. +**Why rejoin matters for key recovery.** If no join is on the air, the Transport-Key can be forced back onto it: making a device leave and rejoin re-runs the key transport [securelist2025]. The rejoin procedure is itself a documented weakness, Wang et al. (RAID 2022) formally verified that Zigbee's Trust-Center rejoin "sacrifices authenticity to achieve" availability, confirming a known design flaw and revealing two new ones, with proof-of-concept attacks ranging from denial of service to device hijacking against real hubs [wang2022rejoin]. **Rotation.** The Trust Center *may* periodically update the network key and switch devices to it via a broadcast or unicast Transport-Key followed by a Key-Switch command, and the specification recommends periodic rotation to limit the damage of a compromised key [silabs-security][csa-zigbee-r23]. In practice many deployments never rotate, so a key recovered once stays valid for the device's life [securelist2025]. Zillner found across the devices he tested that vendors "implement the minimum of the features required to be certified, including the default TC fallback key" and that "no automatic key rotation could be identified" [zillner2015]. -The "ships with the default key enabled / never rotates" picture is a *representative industry pattern* reported by Zillner (2015) and Securelist (2025), not a per-device guarantee — treat it as a starting hypothesis and confirm against the specific device, stack version and Zigbee profile under test before asserting a given product is affected. Likewise the APS Transport-Key / Key-Switch and install-code key-derivation behaviour here is summarised from the Silicon Labs security documentation and the Securelist assessment; the authoritative normative text is the CSA Zigbee R23 specification (05-3474-23), which this control does not quote verbatim [silabs-security][securelist2025][csa-zigbee-r23]. +The "ships with the default key enabled / never rotates" picture is a *representative industry pattern* reported by Zillner (2015) and Securelist (2025), not a per-device guarantee, treat it as a starting hypothesis and confirm against the specific device, stack version and Zigbee profile under test before asserting a given product is affected. Likewise the APS Transport-Key / Key-Switch and install-code key-derivation behaviour here is summarised from the Silicon Labs security documentation and the Securelist assessment; the authoritative normative text is the CSA Zigbee R23 specification (05-3474-23), which this control does not quote verbatim [silabs-security][securelist2025][csa-zigbee-r23]. ## Procedure @@ -167,19 +167,19 @@ The "ships with the default key enabled / never rotates" picture is a *represent > and must be lawful in your jurisdiction. Do not transmit (the forced-rejoin step) > or decrypt traffic outside the agreed scope. Use your own / in-scope devices. -1. **Find the channel and PAN** (per the SP-layer step / RFSAM-ZIGBEE-SP-01) so you know which of channels 11–26 the target lives on and its PAN ID. Zigbee pins a PAN to one 2 MHz channel and stays there — a channel scan, not a hop chase. +1. **Find the channel and PAN** (per the SP-layer step / RFSAM-ZIGBEE-SP-01) so you know which of channels 11 to 26 the target lives on and its PAN ID. Zigbee pins a PAN to one 2 MHz channel and stays there, a channel scan, not a hop chase. 2. **Park the capture radio on the target channel and capture a device joining.** The join is where the network key is transported and where the whole network opens up. With KillerBee: ```bash zbdump -f 15 -w join.pcap # capture channel 15 to a PCAP ``` - With a CatSniffer, run catnip's 802.15.4/Zigbee sniffer into Wireshark instead. Expected: a PCAP that includes the join exchange — beacon request/response, association, and an **APS Transport-Key** command frame. To get a fresh join, power-cycle or re-pair the in-scope target while capturing. + With a CatSniffer, run catnip's 802.15.4/Zigbee sniffer into Wireshark instead. Expected: a PCAP that includes the join exchange, beacon request/response, association, and an **APS Transport-Key** command frame. To get a fresh join, power-cycle or re-pair the in-scope target while capturing. 3. **Recover the network key from the join capture** with KillerBee's `zbdsniff`: ```bash zbdsniff join.pcap ``` - Expected: when the Transport-Key was protected only by the default link key `ZigBeeAlliance09` (or sent unencrypted), `zbdsniff` prints the recovered 128-bit network key [killerbee]. If it finds no key, either the capture contains no Transport-Key (re-capture a join, step 2) or the transport was protected by a per-device install-code link key — which is the *secure* outcome and itself the finding (record it). + Expected: when the Transport-Key was protected only by the default link key `ZigBeeAlliance09` (or sent unencrypted), `zbdsniff` prints the recovered 128-bit network key [killerbee]. If it finds no key, either the capture contains no Transport-Key (re-capture a join, step 2) or the transport was protected by a per-device install-code link key, which is the *secure* outcome and itself the finding (record it). 4. **Confirm the key decrypts the mesh in Wireshark.** Open the PCAP, then add the recovered key under **Edit → Preferences → Protocols → ZigBee → Pre-configured keys**, and add the default TC link key `ZigBeeAlliance09` as well [securelist2025][silabs-security]. Reload the capture. ```text @@ -189,20 +189,20 @@ The "ships with the default key enabled / never rotates" picture is a *represent ``` Expected: previously-opaque NWK/APS payloads now dissect into readable cluster commands (on/off, level, lock, thermostat) [wireshark-zbee-nwk]. Decryption is the proof the recovered key is correct and that the join transport was weak. -5. **Assess rotation.** Capture the live network over an extended window (or across an authorised forced rejoin) and watch the network-key **sequence number** in NWK security headers. A Trust Center that rotates issues a new Transport-Key + Key-Switch and the sequence number advances [silabs-security][csa-zigbee-r23]. A sequence number that never changes across the observation window indicates the key is not being rotated — so a once-recovered key stays valid indefinitely. +5. **Assess rotation.** Capture the live network over an extended window (or across an authorised forced rejoin) and watch the network-key **sequence number** in NWK security headers. A Trust Center that rotates issues a new Transport-Key + Key-Switch and the sequence number advances [silabs-security][csa-zigbee-r23]. A sequence number that never changes across the observation window indicates the key is not being rotated, so a once-recovered key stays valid indefinitely. 6. **(Optional, transmit) Force a rejoin to re-expose the transport.** Only on an in-scope network and with a transmit-capable radio: provoke a leave/rejoin so a fresh Transport-Key hits the air for capture. KillerBee's framework drives the disruptive scans/floods that provoke a rejoin; note that the rejoin procedure itself carries the flaws Wang et al. document [wang2022rejoin]. ```bash - # KillerBee transmit-capable radio (e.g. ApiMote); disruptive — authorised use only + # KillerBee transmit-capable radio (e.g. ApiMote); disruptive, authorised use only zbstumbler -c 15 # active beacon-request scan that can provoke activity ``` - Expected: the target leaves and rejoins, putting a new Transport-Key on the air; return to step 2 to capture and step 3 to extract. This step transmits into the live network — keep it in scope and time-boxed. + Expected: the target leaves and rejoins, putting a new Transport-Key on the air; return to step 2 to capture and step 3 to extract. This step transmits into the live network, keep it in scope and time-boxed. 7. **Record the result:** join key-transport (default-key / clear / install-code), whether `zbdsniff` recovered the key, whether Wireshark then decrypted NWK/APS, and the rotation observation (sequence number static vs advancing). Each positive is a key-management failure that collapses the mesh's confidentiality. ## Field case -A public KillerBee-shipped sample grounds the default-key / clear-transport row of this field case — no first-party capture is needed to demonstrate the break. The repo's own note (riverloopsec/killerbee, `sample/control4-sample.txt`) describes `sample/control4-sample.pcap` as "a sample packet capture from a Control4 appliance that includes OTA key delivery to a downstream device" that you can "extract the key with zbdsniff, and decrypt the contents with Wireshark" [killerbee-control4-sample]. Dissecting that shipped capture, the join's APS Transport-Key command (a Standard Network Key with key sequence number 0) carries **APS Security: False** — so the network key is delivered over the air in the clear, not even wrapped under `ZigBeeAlliance09` — and `zbdsniff` reads it straight off: the recovered Control4 network key is `26546b723b396a727b5d5271517d392f` [killerbee-control4-sample][killerbee]. (As the same note warns, that key must be entered byte-reversed into Wireshark's pre-configured keys to decrypt the session.) To exercise the secure path for comparison, stand up your own authorised test network, provision one end device with a per-device **install code**, and repeat — `zbdsniff` should fail on that device because the Transport-Key is protected by a key the attacker does not hold. +A public KillerBee-shipped sample grounds the default-key / clear-transport row of this field case, no first-party capture is needed to demonstrate the break. The repo's own note (riverloopsec/killerbee, `sample/control4-sample.txt`) describes `sample/control4-sample.pcap` as "a sample packet capture from a Control4 appliance that includes OTA key delivery to a downstream device" that you can "extract the key with zbdsniff, and decrypt the contents with Wireshark" [killerbee-control4-sample]. Dissecting that shipped capture, the join's APS Transport-Key command (a Standard Network Key with key sequence number 0) carries **APS Security: False**, so the network key is delivered over the air in the clear, not even wrapped under `ZigBeeAlliance09`, and `zbdsniff` reads it straight off: the recovered Control4 network key is `26546b723b396a727b5d5271517d392f` [killerbee-control4-sample][killerbee]. (As the same note warns, that key must be entered byte-reversed into Wireshark's pre-configured keys to decrypt the session.) To exercise the secure path for comparison, stand up your own authorised test network, provision one end device with a per-device **install code**, and repeat, `zbdsniff` should fail on that device because the Transport-Key is protected by a key the attacker does not hold. ```text # network-key provisioning findings; row A = KillerBee-shipped control4-sample.pcap (public) @@ -211,14 +211,14 @@ Control4 appliance none (APS Sec=False) 26546b72…517d392f y [FILL: end device B] per-device install [FILL: no key] [FILL: n] [FILL: seq static?] ``` -The shape is exactly as expected: the clear-transport Control4 device yields its full 128-bit network key from a single sniffed join (its whole mesh is then decryptable in Wireshark), while an install-code device defeats `zbdsniff` because the key never crosses the air in a recoverable form. The historical anchor for the default-key variant is Zillner's Black Hat 2015 result — sniffing a default-key join compromises the active network key, and because Home-Automation door-locks and HVAC use the same profile as light bulbs, the impact is not limited to harmless devices [zillner2015]. +The shape is exactly as expected: the clear-transport Control4 device yields its full 128-bit network key from a single sniffed join (its whole mesh is then decryptable in Wireshark), while an install-code device defeats `zbdsniff` because the key never crosses the air in a recoverable form. The historical anchor for the default-key variant is Zillner's Black Hat 2015 result, sniffing a default-key join compromises the active network key, and because Home-Automation door-locks and HVAC use the same profile as light bulbs, the impact is not limited to harmless devices [zillner2015]. -Row A is the documented public KillerBee sample (`control4-sample.pcap`), not a first-party live capture — re-derive it locally with `zbdsniff sample/control4-sample.pcap` to confirm [killerbee-control4-sample]. Row B's `[FILL: …]` cells, and both rotation cells, remain placeholders for the reader's own authorised lab run and must not be presented as measured findings. +Row A is the documented public KillerBee sample (`control4-sample.pcap`), not a first-party live capture, re-derive it locally with `zbdsniff sample/control4-sample.pcap` to confirm [killerbee-control4-sample]. Row B's `[FILL: …]` cells, and both rotation cells, remain placeholders for the reader's own authorised lab run and must not be presented as measured findings. ## Remediation **Developer (device / stack).** Do not rely on the well-known default Trust Center link key `ZigBeeAlliance09` for network-key transport: ship Zigbee 3.0+ with a per-device **install code** so the Trust Center derives a unique pre-configured link key for each joining device, and the Transport-Key is protected by a key an over-the-air attacker does not hold [securelist2025][silabs-security]. Never disable APS encryption of the Transport-Key (no clear-text key transport). Where the stack still supports a default-key fallback for interoperability, gate it tightly. Support and honour network-key rotation (Transport-Key + Key-Switch) so a key is not valid for the device's entire life [silabs-security][csa-zigbee-r23]. -**Integrator (hub / Trust Center).** Configure the Trust Center to require install-code-based joining and to permit the insecure default-link-key fallback only during a brief, explicit commissioning window — not as a standing condition — since the well-known key should never protect a network-key transport during normal operation or a rejoin [securelist2025][silabs-security]. Enable periodic network-key rotation. Harden the rejoin path against the abuse Wang et al. document — rate-limit and authenticate rejoin/leave handling so unsolicited devices cannot trivially force rejoins or exhaust resources [wang2022rejoin]. +**Integrator (hub / Trust Center).** Configure the Trust Center to require install-code-based joining and to permit the insecure default-link-key fallback only during a brief, explicit commissioning window, not as a standing condition, since the well-known key should never protect a network-key transport during normal operation or a rejoin [securelist2025][silabs-security]. Enable periodic network-key rotation. Harden the rejoin path against the abuse Wang et al. document, rate-limit and authenticate rejoin/leave handling so unsolicited devices cannot trivially force rejoins or exhaust resources [wang2022rejoin]. -**Operator (deployment).** Treat the network key as the crown jewel of the PAN: prefer install-code commissioning, keep the permit-join window closed except when deliberately adding a device, and where the hub supports it, rotate the network key periodically so a key recovered from one historic join stops being useful [securelist2025][silabs-security]. Periodically run this passive capture-and-extract audit against your own network — a `zbdsniff` recovery from a sniffed join, or a network-key sequence number that never advances, is a provisioning failure to fix, not merely an attacker's opportunity. +**Operator (deployment).** Treat the network key as the crown jewel of the PAN: prefer install-code commissioning, keep the permit-join window closed except when deliberately adding a device, and where the hub supports it, rotate the network key periodically so a key recovered from one historic join stops being useful [securelist2025][silabs-security]. Periodically run this passive capture-and-extract audit against your own network, a `zbdsniff` recovery from a sniffed join, or a network-key sequence number that never advances, is a provisioning failure to fix, not merely an attacker's opportunity. diff --git a/src/content/controls/rfsam-zigbee-ll-01.md b/src/content/controls/rfsam-zigbee-ll-01.md index 9135109..05b1a07 100644 --- a/src/content/controls/rfsam-zigbee-ll-01.md +++ b/src/content/controls/rfsam-zigbee-ll-01.md @@ -10,7 +10,7 @@ applicability: deferred: false objective: >- Determine what network topology and identifiers a passive listener can recover - from a Zigbee/802.15.4 network without any key — the PAN ID and extended PAN + from a Zigbee/802.15.4 network without any key, the PAN ID and extended PAN ID, the operating channel, per-device short (16-bit) and extended (EUI-64) addresses, and the coordinator/router/end-device relationships inferable by pairing source and destination addresses in unencrypted MAC and NWK headers. @@ -18,7 +18,7 @@ intro: >- Zigbee encrypts NWK and APS payloads with AES-128-CCM*, but the IEEE 802.15.4 MAC header and the Zigbee NWK header travel in the clear. A listener parked on the channel can read the PAN ID, both short and extended addresses, frame - control fields and routing addresses without any key — enough to enumerate the + control fields and routing addresses without any key, enough to enumerate the devices, identify the coordinator, and infer the mesh topology. This is observational reconnaissance, not takeover; it establishes what the network leaks before any active step. @@ -28,7 +28,7 @@ prerequisites: software: - 'A capture tool (nRF Sniffer 802.15.4 / whsniff / catnip / KillerBee zbdump, or Kismet for a passive multi-channel survey) feeding Wireshark, whose 802.15.4/Zigbee dissector decodes MAC and NWK headers without a key.' signal: - freq: '2.405–2.480 GHz ISM (16 channels, 11–26, spaced 5 MHz); sub-GHz 868 MHz (Europe) / 902–928 MHz (Americas)' + freq: '2.405 to 2.480 GHz ISM (16 channels, 11 to 26, spaced 5 MHz); sub-GHz 868 MHz (Europe) / 902 to 928 MHz (Americas)' bandwidth: '2 MHz per channel (2.4 GHz)' modulation: 'IEEE 802.15.4 O-QPSK with DSSS, 250 kbps at 2.4 GHz' skill: intermediate @@ -39,7 +39,7 @@ attacks: impact: >- Reconstructs the network's device inventory and parent/child topology from encrypted traffic by pairing the cleartext short MAC addresses of source - and destination packets — without ever holding the network key. + and destination packets, without ever holding the network key. preconditions: >- Passive capture on the target's channel only; the MAC/NWK headers are not encrypted, so no key is required. @@ -63,7 +63,7 @@ attacks: for unknown devices/events, 99.8% for known devices in the paper). references: - key: ieee802154-2024 - title: 'IEEE Std 802.15.4-2024 — IEEE Standard for Low-Rate Wireless Networks' + title: 'IEEE Std 802.15.4-2024: IEEE Standard for Low-Rate Wireless Networks' venue: IEEE year: 2024 url: 'https://standards.ieee.org/ieee/802.15.4/11041/' @@ -83,7 +83,7 @@ references: url: 'https://mews.sv.cmu.edu/papers/wisec-20.pdf' type: paper - key: akestoridis-zigator-repo - title: 'Zigator — a security analysis tool for Zigbee and Thread networks' + title: 'Zigator: a security analysis tool for Zigbee and Thread networks' authors: D.-G. Akestoridis venue: GitHub year: 2020 @@ -104,14 +104,14 @@ references: url: 'https://securelist.com/zigbee-protocol-security-assessment/118373/' type: blog - key: killerbee-repo - title: 'KillerBee — IEEE 802.15.4/ZigBee Security Research Toolkit' + title: 'KillerBee: IEEE 802.15.4/ZigBee Security Research Toolkit' authors: River Loop Security venue: GitHub year: 2024 url: 'https://github.com/riverloopsec/killerbee' type: tool - key: wireshark-802154 - title: 'Wireshark — IEEE 802.15.4 dissector reference' + title: 'Wireshark: IEEE 802.15.4 dissector reference' venue: Wireshark Wiki url: 'https://wiki.wireshark.org/IEEE_802.15.4' type: tool @@ -135,15 +135,15 @@ lastResearched: 2026-06-14 ## Mechanism -Zigbee runs on IEEE 802.15.4, which carries security at the MAC and (for Zigbee) NWK/APS layers but **does not encrypt frame headers** — the MAC header and the Zigbee NWK header are always in the clear, even when the payload is AES-128-CCM* protected [akestoridis2020zigator] [ieee802154-2024] [zigbee-spec-csa]. A listener that parks an 802.15.4 radio on the target channel can therefore read, with no key at all: the 16-bit **PAN ID**, the **short (16-bit) and extended (EUI-64) source and destination addresses**, and the frame control fields [kabibo2025securelist]. The Securelist industrial assessment states it plainly: "Even when Zigbee payloads are encrypted, the network and MAC headers remain visible. That means we can usually read things like source and destination addresses, PAN ID, short and extended MAC addresses, and frame control fields" [kabibo2025securelist]. +Zigbee runs on IEEE 802.15.4, which carries security at the MAC and (for Zigbee) NWK/APS layers but **does not encrypt frame headers**, the MAC header and the Zigbee NWK header are always in the clear, even when the payload is AES-128-CCM* protected [akestoridis2020zigator] [ieee802154-2024] [zigbee-spec-csa]. A listener that parks an 802.15.4 radio on the target channel can therefore read, with no key at all: the 16-bit **PAN ID**, the **short (16-bit) and extended (EUI-64) source and destination addresses**, and the frame control fields [kabibo2025securelist]. The Securelist industrial assessment states it plainly: "Even when Zigbee payloads are encrypted, the network and MAC headers remain visible. That means we can usually read things like source and destination addresses, PAN ID, short and extended MAC addresses, and frame control fields" [kabibo2025securelist]. -Two kinds of finding follow from those cleartext fields. First, **identifier enumeration**: the PAN ID and extended PAN ID name the network, the operating channel locates it (Zigbee pins a PAN to one 2 MHz channel, 11–26, and stays there), and each device exposes a short address and — when it sends frames with extended addressing — its globally-unique EUI-64, a stable per-device identifier that supports tracking [zigbee-spec-csa] [kabibo2025securelist]. Second, **topology inference**: the Zigator work shows that by pairing the cleartext short MAC addresses of source and destination across captured packets, an attacker infers which devices communicate with which — reconstructing the coordinator/router/end-device relationships of the mesh without ever decrypting a payload [akestoridis2020zigator] [akestoridis-zigator-repo]. ZLeaks extends the point to the application level: from encrypted traffic alone, addressing and periodic-reporting metadata identify in-home devices and infer user events [shafqat2022zleaks]. +Two kinds of finding follow from those cleartext fields. First, **identifier enumeration**: the PAN ID and extended PAN ID name the network, the operating channel locates it (Zigbee pins a PAN to one 2 MHz channel, 11 to 26, and stays there), and each device exposes a short address and, when it sends frames with extended addressing, its globally-unique EUI-64, a stable per-device identifier that supports tracking [zigbee-spec-csa] [kabibo2025securelist]. Second, **topology inference**: the Zigator work shows that by pairing the cleartext short MAC addresses of source and destination across captured packets, an attacker infers which devices communicate with which, reconstructing the coordinator/router/end-device relationships of the mesh without ever decrypting a payload [akestoridis2020zigator] [akestoridis-zigator-repo]. ZLeaks extends the point to the application level: from encrypted traffic alone, addressing and periodic-reporting metadata identify in-home devices and infer user events [shafqat2022zleaks]. -Device discovery has an active counterpart worth knowing: a joining device broadcasts a **beacon request** across channels, and nearby coordinators/routers answer with **beacons** that advertise PAN ID, extended PAN ID, the coordinator address and stack profile in cleartext [kabibo2025securelist] [zigbee-spec-csa]. An assessor can provoke this with an active scan (KillerBee `zbstumbler` transmits beacon requests while channel-hopping [killerbee-repo]) — but transmitting beacon requests is an **active** step and must be authorised. The purely passive path is to listen for the beacons that occur naturally and the data frames that reveal addressing. +Device discovery has an active counterpart worth knowing: a joining device broadcasts a **beacon request** across channels, and nearby coordinators/routers answer with **beacons** that advertise PAN ID, extended PAN ID, the coordinator address and stack profile in cleartext [kabibo2025securelist] [zigbee-spec-csa]. An assessor can provoke this with an active scan (KillerBee `zbstumbler` transmits beacon requests while channel-hopping [killerbee-repo]), but transmitting beacon requests is an **active** step and must be authorised. The purely passive path is to listen for the beacons that occur naturally and the data frames that reveal addressing. ## Procedure -Authorised testing only: capture on a network you own or are explicitly permitted to assess. Steps 1–4 are fully passive (receive-only). Step 5 (active beacon-request scan) **transmits** into the band and must be separately authorised — skip it if you only have passive authorisation. +Authorised testing only: capture on a network you own or are explicitly permitted to assess. Steps 1 to 4 are fully passive (receive-only). Step 5 (active beacon-request scan) **transmits** into the band and must be separately authorised, skip it if you only have passive authorisation. 1. **Find the channel.** Identify the operating channel before capturing. Use a passive survey rather than transmitting: ```bash @@ -167,7 +167,7 @@ Authorised testing only: capture on a network you own or are explicitly permitte ``` Read off, per frame: `wpan.src16` / `wpan.dst16` (short addresses), `wpan.src64` / `wpan.dst64` (EUI-64 when present), `wpan.src_pan` (PAN ID), and `zbee_nwk.src` / `zbee_nwk.dst` (NWK short addresses). Beacon frames (`wpan.frame_type == 0`) carry the PAN parameters and, for Zigbee, the extended PAN ID and stack profile. -4. **Build the inventory and infer topology.** Collect the distinct short addresses and EUI-64s into a device list, then pair source↔destination short addresses across data frames to infer who talks to whom — the coordinator (short address `0x0000`) sits at the root; routers relay; end devices talk only to their parent [akestoridis2020zigator]. The Zigator tool automates this parsing and pairing over a pcap: +4. **Build the inventory and infer topology.** Collect the distinct short addresses and EUI-64s into a device list, then pair source↔destination short addresses across data frames to infer who talks to whom, the coordinator (short address `0x0000`) sits at the root; routers relay; end devices talk only to their parent [akestoridis2020zigator]. The Zigator tool automates this parsing and pairing over a pcap: ```bash zigator parse-pcap-file capture.pcap ``` @@ -177,18 +177,18 @@ Authorised testing only: capture on a network you own or are explicitly permitte ```bash zbstumbler -c 20 ``` - `zbstumbler` transmits beacon requests while channel-hopping and prints summarized information about the devices that answer [killerbee-repo]. This **transmits** — only run it with explicit authorisation on your own/permitted network. + `zbstumbler` transmits beacon requests while channel-hopping and prints summarized information about the devices that answer [killerbee-repo]. This **transmits**, only run it with explicit authorisation on your own/permitted network. ## Field case Walkthrough against Zigator's shipped test capture (akestoridis/zigator, `zigator/tests/data/03-nwk-testing.pcap`; the decoded result is documented in the project's integration test, `zigator/tests/test_integration.py`) [akestoridis-zigator-repo]. These are crafted test fixtures, not a live network, but they reproduce exactly what a passive listener recovers from cleartext headers with no key: parsing the pcap and reading off PAN IDs, short and extended addresses, beacon parameters and the inferred topology. To reproduce against your own consenting network, substitute the identifiers you capture for the ones below. -Running `zigator parse-pcap-file 03-nwk-testing.pcap` over the fixture and inspecting the produced tables — with **no network key loaded** — resolves every header. The capture carries two PANs. In the larger cluster (PAN `0x7777`) the coordinator announces itself at short address `0x0000` and discloses EUI-64 `77:77:77:00:00:00:00:01` in extended-addressing frames; the `short_addresses` table lists **5** devices — `0x0000` (Zigbee Coordinator, FFD), routers `0x1102` and `0x1101` (both FFD), and leaf devices `0x2201` and `0x2202` — each bound to a globally-unique EUI-64 (`7777770000000001`–`7777770000000005`), a stable per-device identifier that persists across rejoins [akestoridis-zigator-repo]. Pairing source/destination short addresses across the captured frames recovers the topology directly from Zigator's `pairs` table: leaf devices `0x2201` and `0x2202` each talk to router `0x1102`, which in turn talks up to coordinator `0x0000` and across to router `0x1101` — i.e. `0x2201→0x1102`, `0x2202→0x1102`, `0x1102→0x0000`, `0x1102→0x1101`. That marks `0x1102` as a router relaying for its children, exactly the parent/child structure of a Zigbee mesh, derived without ever decrypting a payload. The second PAN (`0x99aa`) is named by a beacon whose extended PAN ID is `facefeedbeefcafe`, recovered from the cleartext `nwk_beacon_epid` field, with source extended address `1122334455667788` exposed in the clear. The integration test asserts these decoded values verbatim — PAN `0x99aa` with extended PAN ID `facefeedbeefcafe` in the `networks` table, and the `0x7777` short-address/EUI-64/role rows in `short_addresses` — confirming that this is precisely what the dissector yields [akestoridis-zigator-repo]. None of it required the network key, only the capture on the right channel, which is the finding the control verifies: **topology and persistent identifiers leak in the clear** [akestoridis2020zigator] [akestoridis-zigator-repo] [kabibo2025securelist]. +Running `zigator parse-pcap-file 03-nwk-testing.pcap` over the fixture and inspecting the produced tables, with **no network key loaded**, resolves every header. The capture carries two PANs. In the larger cluster (PAN `0x7777`) the coordinator announces itself at short address `0x0000` and discloses EUI-64 `77:77:77:00:00:00:00:01` in extended-addressing frames; the `short_addresses` table lists **5** devices, `0x0000` (Zigbee Coordinator, FFD), routers `0x1102` and `0x1101` (both FFD), and leaf devices `0x2201` and `0x2202`, each bound to a globally-unique EUI-64 (`7777770000000001` to `7777770000000005`), a stable per-device identifier that persists across rejoins [akestoridis-zigator-repo]. Pairing source/destination short addresses across the captured frames recovers the topology directly from Zigator's `pairs` table: leaf devices `0x2201` and `0x2202` each talk to router `0x1102`, which in turn talks up to coordinator `0x0000` and across to router `0x1101`, i.e. `0x2201→0x1102`, `0x2202→0x1102`, `0x1102→0x0000`, `0x1102→0x1101`. That marks `0x1102` as a router relaying for its children, exactly the parent/child structure of a Zigbee mesh, derived without ever decrypting a payload. The second PAN (`0x99aa`) is named by a beacon whose extended PAN ID is `facefeedbeefcafe`, recovered from the cleartext `nwk_beacon_epid` field, with source extended address `1122334455667788` exposed in the clear. The integration test asserts these decoded values verbatim, PAN `0x99aa` with extended PAN ID `facefeedbeefcafe` in the `networks` table, and the `0x7777` short-address/EUI-64/role rows in `short_addresses`, confirming that this is precisely what the dissector yields [akestoridis-zigator-repo]. None of it required the network key, only the capture on the right channel, which is the finding the control verifies: **topology and persistent identifiers leak in the clear** [akestoridis2020zigator] [akestoridis-zigator-repo] [kabibo2025securelist]. ## Remediation -The header exposure is inherent to IEEE 802.15.4 — MAC and NWK headers are not encrypted by design — so remediation is about limiting what those identifiers reveal and how usable they are, not eliminating the leak [ieee802154-2024] [akestoridis2020zigator]. +The header exposure is inherent to IEEE 802.15.4, MAC and NWK headers are not encrypted by design, so remediation is about limiting what those identifiers reveal and how usable they are, not eliminating the leak [ieee802154-2024] [akestoridis2020zigator]. - **Developer (stack/firmware).** Prefer NWK addressing that minimises extended-address (EUI-64) disclosure on air: once a device has a short address, avoid sending frames with the full EUI-64 in the clear where the spec allows the short form, to reduce the stable-identifier footprint [zigbee-spec-csa]. Do not place any sensitive identifier (serials, user IDs) in cleartext header or beacon fields. Where the platform supports MAC-layer source-address randomisation or topology-obfuscation features, expose and document them. -- **Integrator (product/hub).** Treat the network as observable: assume an unauthorised listener already knows the PAN ID, channel, device count and topology, and design so that knowledge alone grants nothing — keep all command authority behind the encrypted APS/ZCL layer with a properly provisioned network key and per-device install codes (not the well-known default Trust Center link key) [zigbee-spec-csa] [kabibo2025securelist]. Avoid encoding device function in predictable address patterns. +- **Integrator (product/hub).** Treat the network as observable: assume an unauthorised listener already knows the PAN ID, channel, device count and topology, and design so that knowledge alone grants nothing, keep all command authority behind the encrypted APS/ZCL layer with a properly provisioned network key and per-device install codes (not the well-known default Trust Center link key) [zigbee-spec-csa] [kabibo2025securelist]. Avoid encoding device function in predictable address patterns. - **Operator (deployment).** Recognise that metadata leaks even under encryption: device presence, count and activity (event timing) are inferable passively [shafqat2022zleaks]. For sensitive sites, factor this into siting and shielding decisions, monitor for unexpected beacon-request scans (an active discovery attempt), and prefer the highest-assurance join model (install-code-only joining) so that observing the network yields reconnaissance but no path to join or decrypt. diff --git a/src/content/controls/rfsam-zigbee-sp-01.md b/src/content/controls/rfsam-zigbee-sp-01.md index 736224e..2101c76 100644 --- a/src/content/controls/rfsam-zigbee-sp-01.md +++ b/src/content/controls/rfsam-zigbee-sp-01.md @@ -10,11 +10,11 @@ applicability: deferred: false objective: >- Determine which 802.15.4 channel(s) carry the target PAN and whether that PAN - can be observed from the assessment position — i.e. confirm the channel, PAN ID + can be observed from the assessment position, i.e. confirm the channel, PAN ID and a usable signal before committing a capture radio to the link layer. intro: >- A 2.4 GHz Zigbee PAN is pinned to one of sixteen fixed 802.15.4 channels and - stays there — it does not frequency-hop. The Spectrum-layer job is therefore a + stays there, it does not frequency-hop. The Spectrum-layer job is therefore a channel scan, not a hop chase: find the channel the network lives on, read its PAN ID, and judge whether the signal is strong and clean enough (against heavy Wi-Fi overlap in this band) to capture. This control is observational; it @@ -26,7 +26,7 @@ prerequisites: software: - 'A channel/PAN scanner: KillerBee (zbstumbler, active) or Kismet (passive 802.15.4 survey); catnip cativity on a CatSniffer; gqrx for the SDR waterfall' signal: - freq: '2.4 GHz: 16 channels 11–26, centre Fc = 2405 + 5(k−11) MHz (2405–2480 MHz), spaced 5 MHz' + freq: '2.4 GHz: 16 channels 11 to 26, centre Fc = 2405 + 5(k−11) MHz (2405 to 2480 MHz), spaced 5 MHz' bandwidth: '~2 MHz occupied per channel' modulation: 'IEEE 802.15.4 O-QPSK with DSSS, 250 kbps (2.4 GHz PHY)' skill: beginner @@ -36,7 +36,7 @@ attacks: - killerbee - ieee802154-2020 impact: >- - Enumerates reachable PANs — channel, 16-bit PAN ID and stack/profile hints — + Enumerates reachable PANs, channel, 16-bit PAN ID and stack/profile hints, without joining or decrypting; the reconnaissance that precedes any capture or attack, not an exploit in itself. preconditions: >- @@ -45,54 +45,54 @@ attacks: beacon-enabled or association-permitting coordinator). summary: >- zbstumbler walks the channels transmitting 802.15.4 beacon requests and - logs the PANs that answer (PAN ID, channel, stack profile) — an active scan + logs the PANs that answer (PAN ID, channel, stack profile), an active scan that locates the network fast. Because it transmits, prefer a passive energy/Kismet sweep where stealth or non-interference matters. references: - key: ieee802154-2020 - title: 'IEEE Std 802.15.4-2020 — IEEE Standard for Low-Rate Wireless Networks (PHY/MAC; 2.4 GHz O-QPSK PHY, channel pages 11–26, ED and active scanning)' + title: 'IEEE Std 802.15.4-2020: IEEE Standard for Low-Rate Wireless Networks (PHY/MAC; 2.4 GHz O-QPSK PHY, channel pages 11 to 26, ED and active scanning)' authors: IEEE 802.15 Working Group venue: IEEE Standards Association year: 2020 url: 'https://standards.ieee.org/ieee/802.15.4/7029/' type: standard - key: killerbee - title: 'KillerBee — IEEE 802.15.4/ZigBee Security Research Toolkit (zbstumbler active network discovery)' + title: 'KillerBee: IEEE 802.15.4/ZigBee Security Research Toolkit (zbstumbler active network discovery)' authors: River Loop Security (riverloopsec) venue: GitHub year: 2023 url: 'https://github.com/riverloopsec/killerbee' type: tool - key: catsniffer-tools - title: 'CatSniffer-Tools / catnip — cativity 802.15.4 channel-activity monitor and topology discovery' + title: 'CatSniffer-Tools / catnip: cativity 802.15.4 channel-activity monitor and topology discovery' authors: Electronic Cats venue: GitHub year: 2025 url: 'https://github.com/ElectronicCats/CatSniffer-Tools' type: tool - key: kismet - title: 'Kismet — passive 802.15.4 / Zigbee channel survey and pcapng logging' + title: 'Kismet: passive 802.15.4 / Zigbee channel survey and pcapng logging' authors: Mike Kershaw (kismetwireless) venue: GitHub year: 2025 url: 'https://github.com/kismetwireless/kismet' type: tool - key: silabs-an1017 - title: 'Driving Wi-Fi, ZigBee and Thread Coexistence in the 2.4 GHz Band, Part 1: Unmanaged Coexistence (Silicon Labs AN1017 content — frequency separation tolerates ~20 dB more Wi-Fi than adjacent-channel; Zigbee ch 25/26 require reduced TX power for FCC in North America)' + title: 'Driving Wi-Fi, ZigBee and Thread Coexistence in the 2.4 GHz Band, Part 1: Unmanaged Coexistence (Silicon Labs AN1017 content: frequency separation tolerates ~20 dB more Wi-Fi than adjacent-channel; Zigbee ch 25/26 require reduced TX power for FCC in North America)' authors: Silicon Labs venue: Embedded Computing Design year: 2017 url: 'https://embeddedcomputing.com/application/networking-5g/visualization-orchestration-management/driving-wi-fi-zigbee-and-thread-coexistence-in-the-2-4-ghz-band-part-1-unmanaged-coexistence' type: blog - key: metageek-coex - title: 'ZigBee and Wi-Fi Coexistence — Wi-Fi non-overlapping channels 1/6/11 occupy the same frequencies as Zigbee channels 11–22' + title: 'ZigBee and Wi-Fi Coexistence: Wi-Fi non-overlapping channels 1/6/11 occupy the same frequencies as Zigbee channels 11 to 22' authors: MetaGeek (now Oscium) venue: Oscium Training Resources year: 2024 url: 'https://www.oscium.com/training/zigbee-wifi-coexistence/' type: blog - key: haade-zigbee-channels - title: 'Interference between Zigbee and Wi-Fi at 2.4 GHz — the non-overlapping Zigbee channels 15, 20, 25 and 26 sit outside almost all standard Wi-Fi settings' + title: 'Interference between Zigbee and Wi-Fi at 2.4 GHz: the non-overlapping Zigbee channels 15, 20, 25 and 26 sit outside almost all standard Wi-Fi settings' authors: Haade venue: Haade Blog year: 2023 @@ -113,23 +113,23 @@ lastResearched: 2026-06-14 --- ## Mechanism -A 2.4 GHz Zigbee PAN operates on a single IEEE 802.15.4 channel and stays there for the life of the network — unlike BLE, it does not frequency-hop across the band [ieee802154-2020]. The 2.4 GHz PHY defines sixteen channels numbered 11–26, spaced 5 MHz apart, with channel `k` centred at `Fc = 2405 + 5(k − 11)` MHz — i.e. 2405 MHz (ch 11) to 2480 MHz (ch 26) — each occupying roughly 2 MHz, modulated as O-QPSK with DSSS at 250 kbps [ieee802154-2020]. Because the PAN is pinned to one channel, the Spectrum-layer task is a channel scan to find that channel and read the PAN's identity, not a hop chase. +A 2.4 GHz Zigbee PAN operates on a single IEEE 802.15.4 channel and stays there for the life of the network, unlike BLE, it does not frequency-hop across the band [ieee802154-2020]. The 2.4 GHz PHY defines sixteen channels numbered 11 to 26, spaced 5 MHz apart, with channel `k` centred at `Fc = 2405 + 5(k − 11)` MHz, i.e. 2405 MHz (ch 11) to 2480 MHz (ch 26), each occupying roughly 2 MHz, modulated as O-QPSK with DSSS at 250 kbps [ieee802154-2020]. Because the PAN is pinned to one channel, the Spectrum-layer task is a channel scan to find that channel and read the PAN's identity, not a hop chase. -There are two ways to find the channel, and they differ in whether they transmit. An **active scan** sends a MAC beacon request on each channel and records the beacons that answer, yielding the channel, the 16-bit PAN ID and stack/profile hints in seconds; KillerBee's `zbstumbler` is the canonical implementation, walking the channels and logging every PAN that responds [killerbee]. Active scanning is defined by the standard as the coordinator/device discovery primitive [ieee802154-2020], but it is observable to anyone listening and perturbs the network. A **passive survey** instead listens only — an energy/ED-style sweep or a frame-logging channel hop that never sends a beacon request. Kismet channel-hops the 802.15.4 band and logs every PAN, coordinator and device it hears to pcapng without transmitting [kismet]; on a CatSniffer, catnip's `cativity` mode draws a live per-channel activity table and can map coordinator/router/end-device topology [catsniffer-tools]. A wideband SDR waterfall (gqrx) is only a coarse cross-check: it shows energy, not Zigbee frames, and cannot by itself tell Zigbee from Wi-Fi or BLE in the shared band. +There are two ways to find the channel, and they differ in whether they transmit. An **active scan** sends a MAC beacon request on each channel and records the beacons that answer, yielding the channel, the 16-bit PAN ID and stack/profile hints in seconds; KillerBee's `zbstumbler` is the canonical implementation, walking the channels and logging every PAN that responds [killerbee]. Active scanning is defined by the standard as the coordinator/device discovery primitive [ieee802154-2020], but it is observable to anyone listening and perturbs the network. A **passive survey** instead listens only, an energy/ED-style sweep or a frame-logging channel hop that never sends a beacon request. Kismet channel-hops the 802.15.4 band and logs every PAN, coordinator and device it hears to pcapng without transmitting [kismet]; on a CatSniffer, catnip's `cativity` mode draws a live per-channel activity table and can map coordinator/router/end-device topology [catsniffer-tools]. A wideband SDR waterfall (gqrx) is only a coarse cross-check: it shows energy, not Zigbee frames, and cannot by itself tell Zigbee from Wi-Fi or BLE in the shared band. -Capture feasibility is dominated by Wi-Fi coexistence: 802.15.4 shares 2.4 GHz with 802.11, whose ~20 MHz channels overlap several Zigbee channels at once, so a target on a Wi-Fi-congested channel may be hard to capture cleanly. AN1017 frames the defence as *frequency separation* — place the 802.15.4 channel as far as possible from the Wi-Fi channel, ideally at the opposite end of the 2.4 GHz ISM band — because adjacent-channel performance can be up to 20 dB worse than the "far-away" case [silabs-an1017]. The non-overlapping Wi-Fi channels 1/6/11 occupy the same frequencies as Zigbee channels 11–22 [metageek-coex], so practitioners commonly place a PAN on a higher channel above that traffic; the non-overlapping Zigbee channels 15, 20, 25 and 26 sit in the gaps outside almost all standard Wi-Fi settings and are the common choices [haade-zigbee-channels], with channel 26 often the least Wi-Fi-affected but supported by fewer devices. Note a North-American regulatory constraint: AN1017 states Zigbee channels 25 and 26 require reduced transmit power to meet FCC requirements [silabs-an1017]. +Capture feasibility is dominated by Wi-Fi coexistence: 802.15.4 shares 2.4 GHz with 802.11, whose ~20 MHz channels overlap several Zigbee channels at once, so a target on a Wi-Fi-congested channel may be hard to capture cleanly. AN1017 frames the defence as *frequency separation*, place the 802.15.4 channel as far as possible from the Wi-Fi channel, ideally at the opposite end of the 2.4 GHz ISM band, because adjacent-channel performance can be up to 20 dB worse than the "far-away" case [silabs-an1017]. The non-overlapping Wi-Fi channels 1/6/11 occupy the same frequencies as Zigbee channels 11 to 22 [metageek-coex], so practitioners commonly place a PAN on a higher channel above that traffic; the non-overlapping Zigbee channels 15, 20, 25 and 26 sit in the gaps outside almost all standard Wi-Fi settings and are the common choices [haade-zigbee-channels], with channel 26 often the least Wi-Fi-affected but supported by fewer devices. Note a North-American regulatory constraint: AN1017 states Zigbee channels 25 and 26 require reduced transmit power to meet FCC requirements [silabs-an1017]. ## Procedure > Authorised testing only. Step 1 (active scan) transmits 802.15.4 beacon requests into the RF environment; run it only against networks you are authorised to assess, ideally in an RF-shielded setup or with explicit permission. Where stealth or non-interference is required, skip to the passive survey in step 2. -1. **Active scan — find the channel and PAN ID fast (transmits).** Walk the 16 channels with KillerBee, sending beacon requests and logging responders: +1. **Active scan, find the channel and PAN ID fast (transmits).** Walk the 16 channels with KillerBee, sending beacon requests and logging responders: ```bash zbstumbler ``` - Expected output: one line per discovered PAN, e.g. `New Network: PANID 0x1A62 Source 0x0000 Ext PANID ... Channel 15 Stack Profile: ZigBee PRO`. Record the **Channel** and **PANID** of the target — that is the channel you will park a capture radio on. No responders on any channel means the network is out of range, on a non-default channel set, or not answering beacon requests (try the passive survey). + Expected output: one line per discovered PAN, e.g. `New Network: PANID 0x1A62 Source 0x0000 Ext PANID ... Channel 15 Stack Profile: ZigBee PRO`. Record the **Channel** and **PANID** of the target, that is the channel you will park a capture radio on. No responders on any channel means the network is out of range, on a non-default channel set, or not answering beacon requests (try the passive survey). -2. **Passive survey — confirm without transmitting.** Channel-hop and log every PAN/device heard, sending nothing: +2. **Passive survey, confirm without transmitting.** Channel-hop and log every PAN/device heard, sending nothing: ```bash kismet -c nrf52840.0:name=zigbee ``` @@ -142,22 +142,22 @@ Capture feasibility is dominated by Wi-Fi coexistence: 802.15.4 shares 2.4 GHz w ``` Expected: a live per-channel activity table (default mode) highlighting the busy channel, then a fixed-channel detail view and a coordinator/router/end-device topology for the chosen channel. -4. **SDR waterfall — coarse spectrum cross-check (optional).** Tune an SDR to the target channel's centre to judge signal strength and Wi-Fi overlap before committing: +4. **SDR waterfall, coarse spectrum cross-check (optional).** Tune an SDR to the target channel's centre to judge signal strength and Wi-Fi overlap before committing: ```bash gqrx ``` - Tune to `Fc = 2405 + 5(k − 11)` MHz for channel `k` (e.g. 2425 MHz for channel 15). Expected: a ~2 MHz Zigbee burst pattern at the channel centre, often beside much wider Wi-Fi energy. This only confirms energy is present — it does not decode frames; use steps 1–3 to confirm it is Zigbee. + Tune to `Fc = 2405 + 5(k − 11)` MHz for channel `k` (e.g. 2425 MHz for channel 15). Expected: a ~2 MHz Zigbee burst pattern at the channel centre, often beside much wider Wi-Fi energy. This only confirms energy is present, it does not decode frames; use steps 1 to 3 to confirm it is Zigbee. 5. **Record feasibility.** Note channel, PAN ID, observed signal level and the Wi-Fi overlap. This is the hand-off to the LL-layer capture control: the channel to park on and whether capture is clean or contended. ## Field case -Illustrative walkthrough — substitute the values you capture. A bench survey of a Zigbee 3.0 smart-bulb hub on an authorised test network would run as follows. `zbstumbler` (KillerBee, nRF52840) reports a single PAN: PANID `[FILL: observed PAN ID]` on **channel 15** with Stack Profile `ZigBee PRO`. A passive Kismet sweep over the same band confirms the PAN on channel 15 and records `[FILL: device count]` distinct 802.15.4 devices, sending nothing on air. On gqrx tuned to 2425 MHz (channel 15 centre), the ~2 MHz Zigbee bursts appear in a gap beside a Wi-Fi AP on Wi-Fi channel 6, signal `[FILL: measured RSSI/dBm]` — read this against your environment to judge whether capture is clean. Conclusion in this illustration: capture feasible on channel 15; hand off to the LL capture control parked on that channel. The `[FILL: …]` items are placeholders for the values you measure on your own engagement, not reported findings. +Illustrative walkthrough, substitute the values you capture. A bench survey of a Zigbee 3.0 smart-bulb hub on an authorised test network would run as follows. `zbstumbler` (KillerBee, nRF52840) reports a single PAN: PANID `[FILL: observed PAN ID]` on **channel 15** with Stack Profile `ZigBee PRO`. A passive Kismet sweep over the same band confirms the PAN on channel 15 and records `[FILL: device count]` distinct 802.15.4 devices, sending nothing on air. On gqrx tuned to 2425 MHz (channel 15 centre), the ~2 MHz Zigbee bursts appear in a gap beside a Wi-Fi AP on Wi-Fi channel 6, signal `[FILL: measured RSSI/dBm]`, read this against your environment to judge whether capture is clean. Conclusion in this illustration: capture feasible on channel 15; hand off to the LL capture control parked on that channel. The `[FILL: …]` items are placeholders for the values you measure on your own engagement, not reported findings. ## Remediation Channel survey is reconnaissance; "remediation" here is reducing the exposure and interference it depends on, layered by role. - **Developer / stack vendor:** Do not leak network identity before encryption is in force. The channel and PAN ID are inherently observable (they are layer-1/MAC), so the defence is to ensure nothing of value is readable from beacons or pre-join traffic, and to support install-code / Zigbee 3.0 joining so that locating the network does not advance an attacker toward the key (see the CR-layer control). -- **Integrator:** Choose a channel deliberately. Maximizing frequency separation from local Wi-Fi improves reliability [silabs-an1017], and placing the PAN on a higher channel above the common Wi-Fi traffic (e.g. 15/20/25/26) is the usual channel-planning advice [haade-zigbee-channels] — which incidentally also makes the network easier to capture cleanly, so weigh coexistence against exposure, and prefer install-code joining so a located PAN is not a joinable one. Avoid the well-known default Trust Center link key. +- **Integrator:** Choose a channel deliberately. Maximizing frequency separation from local Wi-Fi improves reliability [silabs-an1017], and placing the PAN on a higher channel above the common Wi-Fi traffic (e.g. 15/20/25/26) is the usual channel-planning advice [haade-zigbee-channels], which incidentally also makes the network easier to capture cleanly, so weigh coexistence against exposure, and prefer install-code joining so a located PAN is not a joinable one. Avoid the well-known default Trust Center link key. - **Operator:** Treat the RF environment as observable. A surveyable, fixed-channel PAN is normal and cannot be hidden; monitor for anomalous beacon-request floods or unexpected rejoin activity (signs of active scanning/disruption) and ensure devices that briefly expose identifiers (e.g. at join) do so only during controlled commissioning, not continuously. diff --git a/src/content/controls/rfsam-zwave-cr-01.md b/src/content/controls/rfsam-zwave-cr-01.md index 18e8219..842545c 100644 --- a/src/content/controls/rfsam-zwave-cr-01.md +++ b/src/content/controls/rfsam-zwave-cr-01.md @@ -11,26 +11,26 @@ applicability: deferred: false objective: >- Determine which security class and key-establishment scheme a Z-Wave device - and its controller actually negotiate at inclusion — legacy S0 (AES-128 with + and its controller actually negotiate at inclusion, legacy S0 (AES-128 with the network key transported under a fixed all-zero temporary key), modern S2 (Curve25519 ECDH), unencrypted command classes, or an S2-capable device that - still falls back to S0 — so the exploitability of the rest of the descent is + still falls back to S0, so the exploitability of the rest of the descent is known before any key-recovery is attempted. intro: >- Z-Wave has two security worlds. Legacy S0 sends the network key during inclusion encrypted under a fixed, all-zero temporary key, so capturing one inclusion recovers the key; modern S2 uses a Curve25519 ECDH exchange whose shared secret is never transmitted, removing the capture-the-join shortcut. - This control classifies which scheme is in force — and whether an S2-capable - device still offers S0 (the Z-Shave downgrade) — without yet breaking + This control classifies which scheme is in force, and whether an S2-capable + device still offers S0 (the Z-Shave downgrade), without yet breaking anything. prerequisites: hardware: - 'A sub-GHz SDR tuned to the device region: RTL-SDR V4 (narrow, first-class on this band) or HackRF One (wider survey); or a Silicon Labs UZB stick re-flashed with Zniffer firmware for a turnkey, fully-dissected capture' software: - - 'Waving-Z or rtl-zwave (SDR demod), EZ-Wave / Scapy-radio (HackRF assessment stack), or Silicon Labs Zniffer (vendor sniffer) — to capture and dissect the inclusion exchange and the security command classes' + - 'Waving-Z or rtl-zwave (SDR demod), EZ-Wave / Scapy-radio (HackRF assessment stack), or Silicon Labs Zniffer (vendor sniffer), to capture and dissect the inclusion exchange and the security command classes' signal: - freq: '908.42 MHz (US) · 868.42 MHz (EU) · regional channels (ANZ 921.42, HK 919.82, JP 922–926 MHz); Z-Wave Long Range US 912/920 MHz — one region per device' + freq: '908.42 MHz (US) · 868.42 MHz (EU) · regional channels (ANZ 921.42, HK 919.82, JP 922 to 926 MHz); Z-Wave Long Range US 912/920 MHz, one region per device' bandwidth: 'Narrowband channel per data rate (9.6 / 40 / 100 kbps, R1/R2/R3)' modulation: '(G)FSK, ITU-T G.9959 PHY/MAC' skill: intermediate @@ -43,7 +43,7 @@ attacks: Recovery of the S0 network key from a single captured inclusion, after which all S0 traffic on that network can be decrypted and forged. preconditions: >- - The target is on an S0 network and an inclusion (pairing) is captured — + The target is on an S0 network and an inclusion (pairing) is captured, either observed opportunistically or forced by excluding and re-including the device while capturing. Without an inclusion capture there is no S0 key. summary: >- @@ -79,7 +79,7 @@ attacks: summary: >- Two DoS attacks abuse the fact that inclusion-phase control packets are unencrypted and unauthenticated, illustrating that the inclusion exchange - is the protocol's exposed seam — the same seam the S0 key break exploits. + is the protocol's exposed seam, the same seam the S0 key break exploits. references: - key: fouladi2013 title: Security Evaluation of the Z-Wave Wireless Protocol @@ -110,14 +110,14 @@ references: url: 'https://scholar.afit.edu/etd/304/' type: paper - key: boucif2020crushing - title: 'Crushing the Wave – new Z-Wave vulnerabilities exposed' + title: 'Crushing the Wave: new Z-Wave vulnerabilities exposed' authors: 'N. Boucif, F. Golchert, A. Siemer, P. Felke, F. Gosewehr' venue: arXiv:2001.08497 year: 2020 url: 'https://arxiv.org/abs/2001.08497' type: paper - key: wavingz-readme - title: 'waving-z — README (G.9959 Z-Wave SDR transmit/receive)' + title: 'waving-z: README (G.9959 Z-Wave SDR transmit/receive)' authors: 'baol (waving-z contributors)' venue: GitHub (baol/waving-z) year: 2018 @@ -139,21 +139,21 @@ lastResearched: 2026-06-14 --- ## Mechanism -Z-Wave runs over the open ITU-T G.9959 (G)FSK PHY/MAC in a region-locked sub-GHz ISM slice, and the network is fingerprinted in the clear: a 32-bit Home ID and 8-bit Node ID sit in every frame header. Security is layered above this as command-class encryption, and which scheme is in force is decided once — at device **inclusion** (pairing). This control reads that decision off the air. +Z-Wave runs over the open ITU-T G.9959 (G)FSK PHY/MAC in a region-locked sub-GHz ISM slice, and the network is fingerprinted in the clear: a 32-bit Home ID and 8-bit Node ID sit in every frame header. Security is layered above this as command-class encryption, and which scheme is in force is decided once, at device **inclusion** (pairing). This control reads that decision off the air. -**Legacy S0** uses AES-128 for confidentiality and a single network key shared by all nodes [silabs-ins13474], with data-origin authentication built on a CBC-MAC over AES (the payload itself is encrypted in an AES feedback mode such as OFB) [fouladi2013]. Its flaw is in how that key is delivered: during inclusion the controller transmits the network key encrypted under a hardcoded temporary key that Fouladi and Ghanoun found to be **16 bytes of zero** [fouladi2013]. Because the temporary key is fixed and public, anyone who captured the inclusion exchange can decrypt the key transport and recover the network key, then decrypt — and forge — the rest of the S0 traffic [fouladi2013]. The same work showed the temporary key can also be abused to *reset* a device's network key [fouladi2013]. This is why the paired capture step insists on grabbing an inclusion: no inclusion capture, no S0 key. +**Legacy S0** uses AES-128 for confidentiality and a single network key shared by all nodes [silabs-ins13474], with data-origin authentication built on a CBC-MAC over AES (the payload itself is encrypted in an AES feedback mode such as OFB) [fouladi2013]. Its flaw is in how that key is delivered: during inclusion the controller transmits the network key encrypted under a hardcoded temporary key that Fouladi and Ghanoun found to be **16 bytes of zero** [fouladi2013]. Because the temporary key is fixed and public, anyone who captured the inclusion exchange can decrypt the key transport and recover the network key, then decrypt, and forge, the rest of the S0 traffic [fouladi2013]. The same work showed the temporary key can also be abused to *reset* a device's network key [fouladi2013]. This is why the paired capture step insists on grabbing an inclusion: no inclusion capture, no S0 key. -**Modern S2** (Z-Wave Gen5 / 700-series and later) closes this. Inclusion uses an Elliptic Curve Diffie-Hellman exchange over **Curve25519**; the size of exchanged keys is reduced enough for constrained IoT nodes, and the ECDH shared secret is never transmitted, so an S2 recording yields no key offline [silabs-ins13474]. S2 divides the network into three security classes — Access Control (door locks, garage doors), Authenticated (normal devices), and Unauthenticated — each with its own key, and authenticates the joining node via a Device Specific Key (DSK) whose value is the first 16 bytes of the node's 32-byte ECDH public key [silabs-ins13474]. +**Modern S2** (Z-Wave Gen5 / 700-series and later) closes this. Inclusion uses an Elliptic Curve Diffie-Hellman exchange over **Curve25519**; the size of exchanged keys is reduced enough for constrained IoT nodes, and the ECDH shared secret is never transmitted, so an S2 recording yields no key offline [silabs-ins13474]. S2 divides the network into three security classes, Access Control (door locks, garage doors), Authenticated (normal devices), and Unauthenticated, each with its own key, and authenticates the joining node via a Device Specific Key (DSK) whose value is the first 16 bytes of the node's 32-byte ECDH public key [silabs-ins13474]. -Two findings make "which scheme?" a security question rather than a label. First, the **Z-Shave downgrade**: the Node Info frame sent at inclusion is unencrypted and unauthenticated, so stripping `COMMAND_CLASS_SECURITY_2` (`0x9F`) from it makes the controller believe an S2-capable device lacks S2 and fall back to S0 — re-opening the all-zero-key break against a device that would otherwise have been safe [tierney2018zshave]. For interoperability, S2 nodes may still hold an S0 key, but they transfer it using the S2 temporary ECDH key rather than the vulnerable S0 exchange [silabs-ins13474]. Second, the inclusion-phase control packets are themselves an exposed, unauthenticated seam: Boucif et al. abuse unencrypted inclusion/operation packets (Nonce Get / S2 Nonce Get, Find Nodes In Range) for denial of service against the gateway [boucif2020crushing]. The open-source assessment methodology for reading these exchanges off an SDR is documented in the EZ-Wave framework [hall2016ezwave]. +Two findings make "which scheme?" a security question rather than a label. First, the **Z-Shave downgrade**: the Node Info frame sent at inclusion is unencrypted and unauthenticated, so stripping `COMMAND_CLASS_SECURITY_2` (`0x9F`) from it makes the controller believe an S2-capable device lacks S2 and fall back to S0, re-opening the all-zero-key break against a device that would otherwise have been safe [tierney2018zshave]. For interoperability, S2 nodes may still hold an S0 key, but they transfer it using the S2 temporary ECDH key rather than the vulnerable S0 exchange [silabs-ins13474]. Second, the inclusion-phase control packets are themselves an exposed, unauthenticated seam: Boucif et al. abuse unencrypted inclusion/operation packets (Nonce Get / S2 Nonce Get, Find Nodes In Range) for denial of service against the gateway [boucif2020crushing]. The open-source assessment methodology for reading these exchanges off an SDR is documented in the EZ-Wave framework [hall2016ezwave]. -Generation-to-scheme mapping is a heuristic, not a guarantee: a 700/800-series SoC *supports* S2 but a given network may still have included the device as S0 (or with unencrypted classes) — a node can request several classes yet be granted only the S0 class by a constrained controller [silabs-ins13474]. Confirm the scheme by observing the actual inclusion / security command classes on the wire — do not infer it from the chipset alone. +Generation-to-scheme mapping is a heuristic, not a guarantee: a 700/800-series SoC *supports* S2 but a given network may still have included the device as S0 (or with unencrypted classes), a node can request several classes yet be granted only the S0 class by a constrained controller [silabs-ins13474]. Confirm the scheme by observing the actual inclusion / security command classes on the wire, do not infer it from the chipset alone. The all-zero temporary key was demonstrated by Fouladi and Ghanoun against the AES Z-Wave door locks of the era (their work predates the 500-series and S2) [fouladi2013]; later S2-capable silicon and S2-only configurations remove the exposure. Re-confirm the scheme against the specific target generation and firmware before asserting recoverability rather than inferring it from the protocol's history. ## Procedure -Authorised testing only — on devices you own or have explicit written permission to assess. Steps 1–4 are passive receive; step 5, if performed, **transmits** to force a re-inclusion and must be confined to your own equipment / an RF-shielded environment. +Authorised testing only, on devices you own or have explicit written permission to assess. Steps 1 to 4 are passive receive; step 5, if performed, **transmits** to force a re-inclusion and must be confined to your own equipment / an RF-shielded environment. 1. **Confirm the region and frequency first.** Read the FCC ID / CE marking on the label to fix the band (a radio tuned to the wrong region hears nothing). Park an SDR on the regional centre and watch for the short FSK bursts (RFSAM-RES-01): ```bash @@ -172,9 +172,9 @@ Authorised testing only — on devices you own or have explicit written permissi - `COMMAND_CLASS_SECURITY_2` (`0x9F`) with an ECDH/public-key exchange → **S2** (note the granted class: Access Control / Authenticated / Unauthenticated). - Neither, with payloads readable without a key → **unencrypted command classes** (these exist even on secure networks). ```text - Expected (S0): a SECURITY key-set/key-transport frame at inclusion — the network + Expected (S0): a SECURITY key-set/key-transport frame at inclusion, the network key encrypted under the fixed all-zero temporary key. - Expected (S2): a SECURITY_2 KEX/public-key exchange — no recoverable key on the wire. + Expected (S2): a SECURITY_2 KEX/public-key exchange, no recoverable key on the wire. ``` 4. **Check whether an S2-capable device still offers S0.** Inspect the device's advertised command classes in its Node Info: if both `0x9F` (S2) and `0x98` (S0) are present, the device is downgrade-eligible (Z-Shave) [tierney2018zshave]. EZ-Wave's recon enumerates supported command classes and the module generation [hall2016ezwave]: @@ -190,15 +190,15 @@ Read the result as: **S0 present** → exploitable via the paired capture + key- ## Field case -Illustrative walkthrough grounded on a documented public frame for the header step. The header values below are taken from the field-labelled transmit example shipped with the waving-z project, not from a live engagement; the security-scheme and downgrade observations remain bracketed `[FILL: …]` placeholders, since no specific inclusion or observed scheme is asserted here. Record your own measured values (and the actual security command classes seen) before citing the scheme/downgrade lines as a finding — do not present those placeholders as a result. +Illustrative walkthrough grounded on a documented public frame for the header step. The header values below are taken from the field-labelled transmit example shipped with the waving-z project, not from a live engagement; the security-scheme and downgrade observations remain bracketed `[FILL: …]` placeholders, since no specific inclusion or observed scheme is asserted here. Record your own measured values (and the actual security command classes seen) before citing the scheme/downgrade lines as a finding, do not present those placeholders as a result. -- **Region.** A US-band Z-Wave device surveys at 908.42 MHz and shows event-driven bursts when polled or when its state changes — capture rate set to R3/100 kbps after a no-decode at R1. -- **Header.** The waving-z README documents a field-labelled G.9959 frame whose `wave-out` example encodes exactly the clear-text header this step reads off the air (baol/waving-z, README, EU "Transmit" example) [wavingz-readme]: a `COMMAND_CLASS_SWITCH_BINARY` (`0x25`) SET-ON (`01 ff`) frame on Home ID `0xD6B26208` from controller/hub Node ID `01` to target device Node ID `07`. That documented artifact illustrates the in-the-clear network fingerprint — Home ID `0xD6B26208`, hub at Node ID `01`, target at Node ID `07` — which is the filter for everything that follows on a real capture. -- **Inclusion.** Excluding and re-including the lock while the Zniffer captures shows the security handshake. If a `COMMAND_CLASS_SECURITY` (`0x98`) key-transport frame appears, the network is **S0** and the network key is being carried encrypted under the all-zero temporary key [fouladi2013] — the recovery is then performed under the paired capture/crypto control, not here. If a `COMMAND_CLASS_SECURITY_2` (`0x9F`) KEX/public-key exchange appears instead, the network is **S2** over Curve25519 [silabs-ins13474] and there is no key to recover offline; the assessment of this control ends at that classification. +- **Region.** A US-band Z-Wave device surveys at 908.42 MHz and shows event-driven bursts when polled or when its state changes, capture rate set to R3/100 kbps after a no-decode at R1. +- **Header.** The waving-z README documents a field-labelled G.9959 frame whose `wave-out` example encodes exactly the clear-text header this step reads off the air (baol/waving-z, README, EU "Transmit" example) [wavingz-readme]: a `COMMAND_CLASS_SWITCH_BINARY` (`0x25`) SET-ON (`01 ff`) frame on Home ID `0xD6B26208` from controller/hub Node ID `01` to target device Node ID `07`. That documented artifact illustrates the in-the-clear network fingerprint, Home ID `0xD6B26208`, hub at Node ID `01`, target at Node ID `07`, which is the filter for everything that follows on a real capture. +- **Inclusion.** Excluding and re-including the lock while the Zniffer captures shows the security handshake. If a `COMMAND_CLASS_SECURITY` (`0x98`) key-transport frame appears, the network is **S0** and the network key is being carried encrypted under the all-zero temporary key [fouladi2013], the recovery is then performed under the paired capture/crypto control, not here. If a `COMMAND_CLASS_SECURITY_2` (`0x9F`) KEX/public-key exchange appears instead, the network is **S2** over Curve25519 [silabs-ins13474] and there is no key to recover offline; the assessment of this control ends at that classification. - **Downgrade check.** The lock's Node Info `[FILL: lists / does not list]` both `0x9F` and `0x98`; if both are present the device is Z-Shave-eligible [tierney2018zshave]. ## Remediation - **Developer (device / silicon).** Ship S2 and refuse to include under S0: do not advertise `COMMAND_CLASS_SECURITY` (`0x98`) on new products. S2's Curve25519 ECDH never puts a recoverable key on the wire [silabs-ins13474]; the S0 all-zero temporary key is the root cause to eliminate [fouladi2013]. Disable the temporary key after the initial network-key set so it cannot be reused to reset the key [fouladi2013]. -- **Integrator (controller / hub).** Use a certified S2 controller and configure it to require S2 (reject S0 fallback) for security-relevant devices — door locks belong in the S2 Access Control class [silabs-ins13474]. Verify the device's DSK out-of-band (QR/printed) at inclusion so a downgraded or spoofed Node Info cannot silently weaken the join [tierney2018zshave]. Treat any device that still negotiates S0 as needing replacement or isolation. -- **Operator (deployment).** Perform inclusion in a controlled setting (S2 authentication via the DSK), minimising the window an attacker could sit in RF range to capture or downgrade a pairing event [tierney2018zshave]. Periodically re-audit which scheme each node actually runs (chipset capability is not configuration) and watch for unexpected re-inclusions — the inclusion phase is the exposed seam for both key recovery and DoS [boucif2020crushing]. +- **Integrator (controller / hub).** Use a certified S2 controller and configure it to require S2 (reject S0 fallback) for security-relevant devices, door locks belong in the S2 Access Control class [silabs-ins13474]. Verify the device's DSK out-of-band (QR/printed) at inclusion so a downgraded or spoofed Node Info cannot silently weaken the join [tierney2018zshave]. Treat any device that still negotiates S0 as needing replacement or isolation. +- **Operator (deployment).** Perform inclusion in a controlled setting (S2 authentication via the DSK), minimising the window an attacker could sit in RF range to capture or downgrade a pairing event [tierney2018zshave]. Periodically re-audit which scheme each node actually runs (chipset capability is not configuration) and watch for unexpected re-inclusions, the inclusion phase is the exposed seam for both key recovery and DoS [boucif2020crushing]. diff --git a/src/content/controls/rfsam-zwave-sp-01.md b/src/content/controls/rfsam-zwave-sp-01.md index 60b58a3..61c1daf 100644 --- a/src/content/controls/rfsam-zwave-sp-01.md +++ b/src/content/controls/rfsam-zwave-sp-01.md @@ -10,25 +10,24 @@ applicability: deferred: false objective: >- Determine which regional sub-GHz channel a Z-Wave device transmits on, confirm - it is actually emitting FSK bursts there, and prove the toolchain can hear them - — so a later capture/decode control tunes the right frequency and data rate from + it is actually emitting FSK bursts there, and prove the toolchain can hear them, so a later capture/decode control tunes the right frequency and data rate from the start instead of staring at a silent waterfall on the wrong region. intro: >- Z-Wave is region-locked: a US device lives at 908.42 MHz and an EU device at - 868.42 MHz, with several other regional channels — and a radio tuned to the + 868.42 MHz, with several other regional channels, and a radio tuned to the wrong one hears nothing. The first RF step is to pin the region, watch the waterfall for the device's short FSK bursts, and confirm reception before any decoder is committed. A cheap RTL-SDR reaches these sub-GHz bands, so this is the band where the budget dongle is a first-class survey radio. prerequisites: hardware: - - 'A receive SDR covering sub-GHz ISM: RTL-SDR Blog V4 (cheap, narrow — one Z-Wave channel is well within range) or a HackRF One (~20 MHz instantaneous bandwidth, to watch several regional channels/rates at once)' + - 'A receive SDR covering sub-GHz ISM: RTL-SDR Blog V4 (cheap, narrow, one Z-Wave channel is well within range) or a HackRF One (~20 MHz instantaneous bandwidth, to watch several regional channels/rates at once)' software: - 'gqrx for a live waterfall; waving-z or rtl-zwave (G.9959 FSK demodulators fed from rtl_sdr/HackRF I/Q) to confirm frames decode' signal: freq: >- Sub-GHz ISM, region-locked: 908.42 MHz (US) · 868.42 MHz (EU) · 921.42 MHz - (ANZ) · 919.82 MHz (HK) · 922–926 MHz (JP) — one region per device. Z-Wave + (ANZ) · 919.82 MHz (HK) · 922 to 926 MHz (JP), one region per device. Z-Wave Long Range adds US 912/920 MHz. bandwidth: 'Narrow FSK channel (tens of kHz of occupied bandwidth); a few hundred kHz of SDR capture span is ample per channel' modulation: 'Classic Z-Wave: (G)FSK per ITU-T G.9959, at three data rates: 9.6 kbps (R1), 40 kbps (R2), 100 kbps (R3). Z-Wave Long Range is different: 100 kbps DSSS-OQPSK (spread spectrum) on US 912/920 MHz.' @@ -36,35 +35,35 @@ prerequisites: attacks: [] references: - key: itu_g9959 - title: 'ITU-T G.9959: Short range narrow-band digital radiocommunication transceivers — PHY, MAC, SAR and LLC layer specifications' + title: 'ITU-T G.9959: Short range narrow-band digital radiocommunication transceivers: PHY, MAC, SAR and LLC layer specifications' authors: ITU-T Study Group 15 venue: International Telecommunication Union (ITU-T Recommendation) year: 2015 url: 'https://www.itu.int/rec/T-REC-G.9959' type: standard - key: silabs_regions - title: 'Z-Wave Global Regions — regional RF frequencies and regulatory references' + title: 'Z-Wave Global Regions: regional RF frequencies and regulatory references' authors: Silicon Labs venue: Silicon Labs (vendor documentation) year: 2026 url: 'https://www.silabs.com/wireless/z-wave/global-regions' type: standard - key: silabs_lr - title: 'Z-Wave Long Range Overview — DSSS-OQPSK 100 kbps profile (US 912/920 MHz)' + title: 'Z-Wave Long Range Overview: DSSS-OQPSK 100 kbps profile (US 912/920 MHz)' authors: Silicon Labs venue: Silicon Labs (vendor documentation) year: 2026 url: 'https://www.silabs.com/wireless/z-wave/z-wave-long-range-overview' type: standard - key: fouladi2013honey - title: "Honey, I'm Home!! — Hacking Z-Wave Home Automation Systems (Black Hat USA 2013, recorded talk)" + title: "Honey, I'm Home!!: Hacking Z-Wave Home Automation Systems (Black Hat USA 2013, recorded talk)" authors: Behrang Fouladi, Sahand Ghanoun (SensePost) venue: Black Hat USA 2013 year: 2013 url: 'https://www.youtube.com/watch?v=tpth0KHYbD0' type: talk - key: sensepost2013zwave - title: "Honey, I'm home!! — hacking Z-Wave & other Black Hat news" + title: "Honey, I'm home!!: hacking Z-Wave & other Black Hat news" authors: SensePost (Behrang Fouladi, Sahand Ghanoun) venue: SensePost blog year: 2013 @@ -78,28 +77,28 @@ references: url: 'https://www.pentestpartners.com/security-blog/z-shave-exploiting-z-wave-downgrade-attacks/' type: blog - key: wavingz - title: 'waving-z — an ITU-T G.9959 (Z-Wave) (de)modulator fed from rtl_sdr/HackRF I/Q' + title: 'waving-z: an ITU-T G.9959 (Z-Wave) (de)modulator fed from rtl_sdr/HackRF I/Q' authors: baol (G. Bertelli) et al. venue: GitHub year: 2026 url: 'https://github.com/baol/waving-z' type: tool - key: rtlzwave - title: 'rtl-zwave — G.9959 (Z-Wave) demodulator for RTL-SDR' + title: 'rtl-zwave: G.9959 (Z-Wave) demodulator for RTL-SDR' authors: A. Esbensen (andersesbensen) venue: GitHub year: 2026 url: 'https://github.com/andersesbensen/rtl-zwave' type: tool - key: gqrx - title: 'Gqrx — software defined radio receiver (GNU Radio + Qt)' + title: 'Gqrx: software defined radio receiver (GNU Radio + Qt)' authors: A. Csete (csete) et al. venue: GitHub year: 2026 url: 'https://github.com/gqrx-sdr/gqrx' type: tool - key: ezwave - title: 'EZ-Wave — tools for evaluating and exploiting Z-Wave networks using SDRs' + title: 'EZ-Wave: tools for evaluating and exploiting Z-Wave networks using SDRs' authors: J. Hall, B. Ramsey, C. Badenhop (cureHsu fork) venue: GitHub year: 2026 @@ -122,27 +121,27 @@ lastResearched: 2026-06-14 --- ## Mechanism -Z-Wave's PHY and MAC are the open ITU-T Recommendation G.9959 — a short-range narrow-band sub-GHz radio with a preamble, frame, CRC and addressing, donated by the protocol's originators and published by the ITU in 2015 [itu_g9959]. For classic Z-Wave the waveform is (G)FSK: the carrier shifts between two tones, at one of three data rates — 9.6 kbps (R1, legacy), 40 kbps (R2) and 100 kbps (R3) [itu_g9959]. Because classic Z-Wave uses no spread spectrum, a device on the right channel is a plain narrowband FSK burst that a cheap receiver can see directly — but only if it is tuned to the right channel. (Z-Wave Long Range is the exception — a spread-spectrum OQPSK PHY covered below.) +Z-Wave's PHY and MAC are the open ITU-T Recommendation G.9959, a short-range narrow-band sub-GHz radio with a preamble, frame, CRC and addressing, donated by the protocol's originators and published by the ITU in 2015 [itu_g9959]. For classic Z-Wave the waveform is (G)FSK: the carrier shifts between two tones, at one of three data rates, 9.6 kbps (R1, legacy), 40 kbps (R2) and 100 kbps (R3) [itu_g9959]. Because classic Z-Wave uses no spread spectrum, a device on the right channel is a plain narrowband FSK burst that a cheap receiver can see directly, but only if it is tuned to the right channel. (Z-Wave Long Range is the exception, a spread-spectrum OQPSK PHY covered below.) -The defining property at the spectrum layer is that Z-Wave is **region-locked**. Silicon Labs' regional documentation assigns each country/region its approved frequency: roughly 908.42 MHz in the US/North America, 868.42 MHz in Europe, 921.42 MHz in Australia/New Zealand, 919.82 MHz in Hong Kong, and a 922–926 MHz cluster in Japan, each tied to that region's regulatory limit (FCC Part 15.249, EN 300 220, AS/NZS 4268, ARIB STD-T108) [silabs_regions]. A device ships for one region and transmits only on that region's channel, so a radio parked on the wrong one — an EU dongle aimed at a US lock — sees a flat, empty waterfall and produces a false "nothing here". Confirming the region is therefore the first and load-bearing RF decision; the wider Z-Wave descent does not even start until the band is right. Z-Wave Long Range (US-only at present) is a separate profile to account for, and it is **not** the same PHY: it is a fourth channel that uses 100 kbps DSSS-OQPSK — a spread-spectrum waveform on 912 MHz (primary) and 920 MHz (backup) — rather than classic Z-Wave's narrowband FSK, with much higher output power [silabs_lr]. So the "narrowband FSK burst, no spread spectrum" property above describes classic Z-Wave; an LR device is a different, broadband signal and demands matching the demodulator accordingly. +The defining property at the spectrum layer is that Z-Wave is **region-locked**. Silicon Labs' regional documentation assigns each country/region its approved frequency: roughly 908.42 MHz in the US/North America, 868.42 MHz in Europe, 921.42 MHz in Australia/New Zealand, 919.82 MHz in Hong Kong, and a 922 to 926 MHz cluster in Japan, each tied to that region's regulatory limit (FCC Part 15.249, EN 300 220, AS/NZS 4268, ARIB STD-T108) [silabs_regions]. A device ships for one region and transmits only on that region's channel, so a radio parked on the wrong one, an EU dongle aimed at a US lock, sees a flat, empty waterfall and produces a false "nothing here". Confirming the region is therefore the first and load-bearing RF decision; the wider Z-Wave descent does not even start until the band is right. Z-Wave Long Range (US-only at present) is a separate profile to account for, and it is **not** the same PHY: it is a fourth channel that uses 100 kbps DSSS-OQPSK, a spread-spectrum waveform on 912 MHz (primary) and 920 MHz (backup), rather than classic Z-Wave's narrowband FSK, with much higher output power [silabs_lr]. So the "narrowband FSK burst, no spread spectrum" property above describes classic Z-Wave; an LR device is a different, broadband signal and demands matching the demodulator accordingly. -This is an observational, capability control, not an attack — hence `info` criticality. It establishes only that the device is transmitting, on which regional channel, and that the toolchain can hear it. The reason the region/feasibility step matters downstream is the rest of the descent: the public Z-Wave security research that the capture, crypto and attack controls build on all presupposes you can first hear the network. The original Black Hat USA 2013 work by Fouladi and Ghanoun built a dedicated radio capture device ("Z-Force") to intercept Z-Wave and then attack an AES-protected door lock [fouladi2013honey][sensepost2013zwave]; the later Z-Shave downgrade work likewise depends on capturing the inclusion exchange, where legacy S0 transports the network key under a fixed all-zero temporary key [pentestpartners2018zshave]. None of that is reachable until this control succeeds, and none of it works against the wrong region. +This is an observational, capability control, not an attack, hence `info` criticality. It establishes only that the device is transmitting, on which regional channel, and that the toolchain can hear it. The reason the region/feasibility step matters downstream is the rest of the descent: the public Z-Wave security research that the capture, crypto and attack controls build on all presupposes you can first hear the network. The original Black Hat USA 2013 work by Fouladi and Ghanoun built a dedicated radio capture device ("Z-Force") to intercept Z-Wave and then attack an AES-protected door lock [fouladi2013honey][sensepost2013zwave]; the later Z-Shave downgrade work likewise depends on capturing the inclusion exchange, where legacy S0 transports the network key under a fixed all-zero temporary key [pentestpartners2018zshave]. None of that is reachable until this control succeeds, and none of it works against the wrong region. -The on-air confirmation has two complementary halves. A **gqrx** waterfall on the regional centre frequency shows the short FSK bursts a Z-Wave device emits when it reports or is polled — proving the device is alive and on the channel you expect before you commit a decoder [gqrx]. Then a software demodulator — **waving-z** or its ancestor **rtl-zwave**, both G.9959 FSK (de)modulators fed raw I/Q from `rtl_sdr` or a HackRF — turns those bursts into decoded frames, confirming not just energy but real Z-Wave traffic and the clear-text Home ID / Node ID headers [wavingz][rtlzwave]. For a scriptable assessment stack carried into the later steps, the EZ-Wave SDR suite does discovery and enumeration over a HackRF [ezwave]. +The on-air confirmation has two complementary halves. A **gqrx** waterfall on the regional centre frequency shows the short FSK bursts a Z-Wave device emits when it reports or is polled, proving the device is alive and on the channel you expect before you commit a decoder [gqrx]. Then a software demodulator, **waving-z** or its ancestor **rtl-zwave**, both G.9959 FSK (de)modulators fed raw I/Q from `rtl_sdr` or a HackRF, turns those bursts into decoded frames, confirming not just energy but real Z-Wave traffic and the clear-text Home ID / Node ID headers [wavingz][rtlzwave]. For a scriptable assessment stack carried into the later steps, the EZ-Wave SDR suite does discovery and enumeration over a HackRF [ezwave]. -The per-region centre frequencies above (908.42 / 868.42 / 921.42 / 919.82 MHz, JP 922–926 MHz) are read from the Silicon Labs Global Regions page [silabs_regions]. Treat the list as representative, not exhaustive — Silicon Labs adds/adjusts regional profiles over time, and several regions carry more than one channel (e.g. US also lists 916 MHz; ANZ 919.8 and 921.4 MHz) — so confirm the exact channel/data-rate set for a *specific* device against that device's regional model and FCC/CE grant (an IG-step task) before relying on a single number. +The per-region centre frequencies above (908.42 / 868.42 / 921.42 / 919.82 MHz, JP 922 to 926 MHz) are read from the Silicon Labs Global Regions page [silabs_regions]. Treat the list as representative, not exhaustive, Silicon Labs adds/adjusts regional profiles over time, and several regions carry more than one channel (e.g. US also lists 916 MHz; ANZ 919.8 and 921.4 MHz), so confirm the exact channel/data-rate set for a *specific* device against that device's regional model and FCC/CE grant (an IG-step task) before relying on a single number. ## Procedure > Receive-only at this layer: you are listening, not transmitting. Even so, monitor only equipment you own or are explicitly authorised to assess, and stay within the regional spectrum rules for the band you tune. -1. **Pin the region before touching a radio (IG carry-over).** Establish which regional channel the device should be on from its market/label — a US-market unit at ~908.42 MHz, an EU unit at ~868.42 MHz, etc. — using Silicon Labs' regional table [silabs_regions]. This single decision determines every frequency below; a wrong region produces a silent, misleading survey. +1. **Pin the region before touching a radio (IG carry-over).** Establish which regional channel the device should be on from its market/label, a US-market unit at ~908.42 MHz, an EU unit at ~868.42 MHz, etc., using Silicon Labs' regional table [silabs_regions]. This single decision determines every frequency below; a wrong region produces a silent, misleading survey. 2. **Watch the regional channel on a waterfall while triggering the device.** Open gqrx on the receive SDR, tune to the regional centre, and provoke the device (open the door, trip the sensor, poll it from its hub) so it talks [gqrx]: ```bash gqrx ``` - Set the device to RTL-SDR (or HackRF), centre frequency to `908.420 MHz` (US) or `868.420 MHz` (EU), and a sample rate of `2.4 MS/s`. Expected: a short, narrow FSK burst flares on the waterfall each time the device reports or is polled — two closely spaced tones, not a single blinking line. No burst after repeated triggering, on a channel you are sure is right, is itself a finding (device idle, asleep, or — recheck — wrong region). + Set the device to RTL-SDR (or HackRF), centre frequency to `908.420 MHz` (US) or `868.420 MHz` (EU), and a sample rate of `2.4 MS/s`. Expected: a short, narrow FSK burst flares on the waterfall each time the device reports or is polled, two closely spaced tones, not a single blinking line. No burst after repeated triggering, on a channel you are sure is right, is itself a finding (device idle, asleep, or, recheck, wrong region). 3. **Confirm it is really Z-Wave by decoding a frame.** Pipe live I/Q from the SDR into a G.9959 demodulator and read decoded frames. With waving-z fed from `rtl_sdr` [wavingz]: ```bash @@ -152,7 +151,7 @@ The per-region centre frequencies above (908.42 / 868.42 / 921.42 / 919.82 MHz, ```bash rtl_zwave ``` - Expected: decoded Z-Wave frames printed to stdout, each carrying a 32-bit Home ID and an 8-bit Node ID in the clear in the header — the network fingerprint. Seeing those fields resolve confirms genuine Z-Wave traffic on this channel, not just generic ISM energy. If energy is visible on the waterfall but nothing decodes, the data rate is likely mismatched — Z-Wave's three rates (9.6 / 40 / 100 kbps) use different deviation/bandwidth, so a decoder set for one rate misses the others; retry across the rates the device may speak. + Expected: decoded Z-Wave frames printed to stdout, each carrying a 32-bit Home ID and an 8-bit Node ID in the clear in the header, the network fingerprint. Seeing those fields resolve confirms genuine Z-Wave traffic on this channel, not just generic ISM energy. If energy is visible on the waterfall but nothing decodes, the data rate is likely mismatched, Z-Wave's three rates (9.6 / 40 / 100 kbps) use different deviation/bandwidth, so a decoder set for one rate misses the others; retry across the rates the device may speak. 4. **(Optional) Carry the capture into the assessment suite.** For a scriptable path you reuse in the later recon/attack steps, run EZ-Wave's passive discovery over a HackRF rather than the standalone demodulators [ezwave]: ```bash @@ -161,15 +160,15 @@ The per-region centre frequencies above (908.42 / 868.42 / 921.42 / 919.82 MHz, ``` Expected: passive enumeration of Z-Wave devices seen on the channel. This is the same SDR/Scapy plumbing the Z-Wave LL/CR/AT controls build on. -5. **Record the spectrum profile.** Write down the confirmed region and centre frequency, that bursts were observed, the data rate at which frames decoded, the observed Home ID / Node ID(s), and whether this is classic Z-Wave or Z-Wave Long Range. This profile scopes the capture target for the Z-Wave LL (capture/decode) and CR (inclusion/key) controls — including the fact that, to break a legacy S0 network later, you must capture an inclusion, so note whether you can force a re-pair while capturing [pentestpartners2018zshave]. +5. **Record the spectrum profile.** Write down the confirmed region and centre frequency, that bursts were observed, the data rate at which frames decoded, the observed Home ID / Node ID(s), and whether this is classic Z-Wave or Z-Wave Long Range. This profile scopes the capture target for the Z-Wave LL (capture/decode) and CR (inclusion/key) controls, including the fact that, to break a legacy S0 network later, you must capture an inclusion, so note whether you can force a re-pair while capturing [pentestpartners2018zshave]. ## Field case -Illustrative walkthrough — substitute the values you capture; the narration below describes the *expected* behaviour of this method, not a single measured engagement, and the bracketed `[FILL: …]` fields must come from your own survey before any of it is cited as a finding. +Illustrative walkthrough, substitute the values you capture; the narration below describes the *expected* behaviour of this method, not a single measured engagement, and the bracketed `[FILL: …]` fields must come from your own survey before any of it is cited as a finding. -A Z-Wave door/window sensor believed to be a US-market unit is surveyed with an RTL-SDR Blog V4 in gqrx tuned to 908.420 MHz at 2.4 MS/s. Tripping the sensor should produce a short twin-tone FSK flare on the waterfall — the unmistakable narrowband Z-Wave burst — each time the reed contact opens. Piping `rtl_sdr -f 908420000 -s 2048000 -g 25 -` into waving-z's `wave-in` then decodes the bursts into frames whose clear-text Home ID and Node ID resolve, confirming genuine Z-Wave (not stray 915 MHz ISM traffic) on the channel. +A Z-Wave door/window sensor believed to be a US-market unit is surveyed with an RTL-SDR Blog V4 in gqrx tuned to 908.420 MHz at 2.4 MS/s. Tripping the sensor should produce a short twin-tone FSK flare on the waterfall, the unmistakable narrowband Z-Wave burst, each time the reed contact opens. Piping `rtl_sdr -f 908420000 -s 2048000 -g 25 -` into waving-z's `wave-in` then decodes the bursts into frames whose clear-text Home ID and Node ID resolve, confirming genuine Z-Wave (not stray 915 MHz ISM traffic) on the channel. -The reproducible lesson is the region gate itself: pointed at 868.420 MHz (the EU channel) instead, the identical setup shows an empty waterfall and decodes nothing — the classic false negative this control exists to prevent. Region first, then everything else. +The reproducible lesson is the region gate itself: pointed at 868.420 MHz (the EU channel) instead, the identical setup shows an empty waterfall and decodes nothing, the classic false negative this control exists to prevent. Region first, then everything else. For a documented public example of the clear-text Z-Wave header this control reads, the waving-z documentation gives a worked G.9959 frame with every field labelled [wavingz]: a transmit command of the form `./wave-out -p 'd6 b2 62 08 01 41 03 0d 07 25 01 ff'` maps to Home ID `d6 b2 62 08` (32-bit), Source/Node ID `01`, FrameCtl `41 03`, LEN `0d`, Dest ID `07`, command class `0x25` (`COMMAND_CLASS_SWITCH_BINARY`) and command `01 ff` (ON; `01 00` is OFF). That is exactly the clear-text Home ID + Node ID layout `wave-in` prints when it decodes a received burst (HomeId, SourceID, FrameCtl, LEN, DestID, CommandClass), so the published example illustrates the same header fields a real survey would read off the air. @@ -178,13 +177,13 @@ Concrete numbers for a worked write-up (fill from a real survey; do not present - Device and believed region/model: [FILL: device + FCC ID / regional model]. - Confirmed centre frequency the bursts appeared on: [FILL: e.g. 908.42 MHz]. - Data rate at which frames decoded: [FILL: 9.6 / 40 / 100 kbps]. -- Observed Home ID / Node ID(s): in the waving-z worked frame [wavingz] the labelled fields are Home ID `d6 b2 62 08` (hex) and Source/Node ID `01` (decimal 1), with Dest ID `07` (decimal 7) — illustrating the hex Home ID + decimal Node ID a live survey records here. +- Observed Home ID / Node ID(s): in the waving-z worked frame [wavingz] the labelled fields are Home ID `d6 b2 62 08` (hex) and Source/Node ID `01` (decimal 1), with Dest ID `07` (decimal 7), illustrating the hex Home ID + decimal Node ID a live survey records here. - Classic Z-Wave vs Z-Wave Long Range: [FILL]. ## Remediation -Capture feasibility is a baseline property of an open sub-GHz FSK radio, not a fixable defect — anyone with a ~$30 RTL-SDR on the right regional channel can see and decode the clear-text frame headers (Home ID, Node ID). The mitigations live one layer up, in what the frames *carry* and how the network is paired, and are layered by who owns the design: +Capture feasibility is a baseline property of an open sub-GHz FSK radio, not a fixable defect, anyone with a ~$30 RTL-SDR on the right regional channel can see and decode the clear-text frame headers (Home ID, Node ID). The mitigations live one layer up, in what the frames *carry* and how the network is paired, and are layered by who owns the design: - **Developer (device/firmware):** Treat every transmitted frame as fully observable. Do not rely on the header identifiers (Home ID / Node ID, sent in clear by design) for any security decision, and do not send security-relevant command classes unencrypted. Prefer modern S2 (Curve25519 ECDH at inclusion) over legacy S0, whose network key is transported under a fixed all-zero temporary key and is recoverable by anyone who captured the inclusion [pentestpartners2018zshave][fouladi2013honey]. -- **Integrator (product/system):** Choose modules and controllers that support and enforce S2, and verify empirically — run the gqrx + waving-z survey above against your own unit on its regional channel, confirm which command classes appear in clear, and confirm the controller does not silently fall back to S0 (the Z-Shave downgrade premise) when an S2 device is included [pentestpartners2018zshave]. Confirm the device's regional frequency and profile match its market grant. -- **Operator (deployment):** Assume the network is observable from outside the premises by anyone tuned to your region's Z-Wave channel; "it's wireless and proprietary" is not confidentiality. For high-value functions (locks, sensors), prefer devices that pair with S2, perform inclusions deliberately and out of band where possible (an attacker needs to capture the join to break S0), and rely on the upper-layer Z-Wave crypto controls — not on transmission obscurity — for confidentiality and replay protection. +- **Integrator (product/system):** Choose modules and controllers that support and enforce S2, and verify empirically, run the gqrx + waving-z survey above against your own unit on its regional channel, confirm which command classes appear in clear, and confirm the controller does not silently fall back to S0 (the Z-Shave downgrade premise) when an S2 device is included [pentestpartners2018zshave]. Confirm the device's regional frequency and profile match its market grant. +- **Operator (deployment):** Assume the network is observable from outside the premises by anyone tuned to your region's Z-Wave channel; "it's wireless and proprietary" is not confidentiality. For high-value functions (locks, sensors), prefer devices that pair with S2, perform inclusions deliberately and out of band where possible (an attacker needs to capture the join to break S0), and rely on the upper-layer Z-Wave crypto controls, not on transmission obscurity, for confidentiality and replay protection. diff --git a/src/content/resources/rfsam-res-01.md b/src/content/resources/rfsam-res-01.md index 2d67407..8dbfe77 100644 --- a/src/content/resources/rfsam-res-01.md +++ b/src/content/resources/rfsam-res-01.md @@ -2,4 +2,4 @@ id: RFSAM-RES-01 title: Capture raw I/Q with an SDR --- -Select an SDR whose instantaneous bandwidth covers the target, tune to the centre frequency, set sample rate ≥ signal bandwidth, and record I/Q to disk. Log overflow/dropped-sample counters — a capture with overflows is silently incomplete. Reference radios: RTL-SDR V4 (narrow), HackRF One (~20 MHz), USRP B210 (~56 MHz, GPSDO), bladeRF 2.0 (~61 MHz). +Select an SDR whose instantaneous bandwidth covers the target, tune to the centre frequency, set sample rate ≥ signal bandwidth, and record I/Q to disk. Log overflow/dropped-sample counters, a capture with overflows is silently incomplete. Reference radios: RTL-SDR V4 (narrow), HackRF One (~20 MHz), USRP B210 (~56 MHz, GPSDO), bladeRF 2.0 (~61 MHz). diff --git a/src/content/resources/rfsam-res-07.md b/src/content/resources/rfsam-res-07.md index 27c2a0a..b2d2dc0 100644 --- a/src/content/resources/rfsam-res-07.md +++ b/src/content/resources/rfsam-res-07.md @@ -2,4 +2,4 @@ id: RFSAM-RES-07 title: Capture and decode LoRa / LoRaWAN --- -Capture the ISM sub-band to I/Q, de-chirp with a soft-decision LoRa demodulator (gr-lora_sdr class), then parse the LoRaWAN frame: MHDR, MType, DevAddr, and — for joins — AppEUI/DevEUI/DevNonce in clear; application payload remains AES-128 encrypted. Classify by MType to profile the network passively. +Capture the ISM sub-band to I/Q, de-chirp with a soft-decision LoRa demodulator (gr-lora_sdr class), then parse the LoRaWAN frame: MHDR, MType, DevAddr, and, for joins, AppEUI/DevEUI/DevNonce in clear; application payload remains AES-128 encrypted. Classify by MType to profile the network passively. diff --git a/src/content/resources/rfsam-res-15.md b/src/content/resources/rfsam-res-15.md index 0f8adc0..6ed8f85 100644 --- a/src/content/resources/rfsam-res-15.md +++ b/src/content/resources/rfsam-res-15.md @@ -2,4 +2,4 @@ id: RFSAM-RES-15 title: 'Discover, demodulate and replay a Sub-GHz signal' --- -Use a wideband SDR (HackRF) to discover and characterise the burst (frequency, OOK/FSK, bitrate) — Ossmann's 'Rapid Radio Reversing' workflow. Demodulate and reverse the frame in Universal Radio Hacker or GNU Radio. Then drive a CC1101-class transceiver (YARD Stick One + rfcat) at the recovered layer-1 settings to receive, replay or forge. For brute force, generate a De Bruijn sequence (OpenSesame). For rolling codes, assess jam-and-capture (RollJam) and sequential replay (RollBack). +Use a wideband SDR (HackRF) to discover and characterise the burst (frequency, OOK/FSK, bitrate), Ossmann's 'Rapid Radio Reversing' workflow. Demodulate and reverse the frame in Universal Radio Hacker or GNU Radio. Then drive a CC1101-class transceiver (YARD Stick One + rfcat) at the recovered layer-1 settings to receive, replay or forge. For brute force, generate a De Bruijn sequence (OpenSesame). For rolling codes, assess jam-and-capture (RollJam) and sequential replay (RollBack). diff --git a/src/content/resources/rfsam-res-16.md b/src/content/resources/rfsam-res-16.md index 3a92fa3..2155a77 100644 --- a/src/content/resources/rfsam-res-16.md +++ b/src/content/resources/rfsam-res-16.md @@ -2,4 +2,4 @@ id: RFSAM-RES-16 title: Survey and capture IEEE 802.15.4 (Zigbee / Thread) --- -Find the channel first with an energy / cativity scan (Zigbee/Thread pin one of the 16 channels 11–26 at 2.4 GHz), then park a real 802.15.4 radio on it — an nRF52840 (nRF Sniffer), a CatSniffer (catnip), a CC2531 (whsniff) or a KillerBee radio — and stream the raw frames into Wireshark over its extcap, where the 802.15.4 + Zigbee/6LoWPAN/Thread dissector decodes MAC, NWK and (with the network key) the upper layers. Crucially, capture a device *joining* — that is where the key is transported and where the network opens up. +Find the channel first with an energy / cativity scan (Zigbee/Thread pin one of the 16 channels 11 to 26 at 2.4 GHz), then park a real 802.15.4 radio on it, an nRF52840 (nRF Sniffer), a CatSniffer (catnip), a CC2531 (whsniff) or a KillerBee radio, and stream the raw frames into Wireshark over its extcap, where the 802.15.4 + Zigbee/6LoWPAN/Thread dissector decodes MAC, NWK and (with the network key) the upper layers. Crucially, capture a device *joining*, that is where the key is transported and where the network opens up. diff --git a/src/content/resources/rfsam-res-17.md b/src/content/resources/rfsam-res-17.md index b27ae0b..85c41e6 100644 --- a/src/content/resources/rfsam-res-17.md +++ b/src/content/resources/rfsam-res-17.md @@ -2,4 +2,4 @@ id: RFSAM-RES-17 title: Recover an 802.15.4 mesh network key from a join --- -To read an encrypted 802.15.4 mesh you need the network key, and the weakness is how that key reaches a joining device. Capture a device joining (the APS Transport-Key on Zigbee; the commissioning exchange on Thread), then recover the key: zbdsniff extracts a Zigbee network key transported under the well-known default Trust Center link key `ZigBeeAlliance09`, while a Thread network key comes from weak / default / exposed commissioning credentials (PSKc, Joiner PSKd) — not from breaking AES. Load the recovered key into Wireshark's protocol preferences to decrypt the capture in place. Modern S2-style ECDH key exchange resists capture-the-join. +To read an encrypted 802.15.4 mesh you need the network key, and the weakness is how that key reaches a joining device. Capture a device joining (the APS Transport-Key on Zigbee; the commissioning exchange on Thread), then recover the key: zbdsniff extracts a Zigbee network key transported under the well-known default Trust Center link key `ZigBeeAlliance09`, while a Thread network key comes from weak / default / exposed commissioning credentials (PSKc, Joiner PSKd), not from breaking AES. Load the recovered key into Wireshark's protocol preferences to decrypt the capture in place. Modern S2-style ECDH key exchange resists capture-the-join. diff --git a/src/content/resources/rfsam-res-20.md b/src/content/resources/rfsam-res-20.md index c2b8515..b210394 100644 --- a/src/content/resources/rfsam-res-20.md +++ b/src/content/resources/rfsam-res-20.md @@ -2,4 +2,4 @@ id: RFSAM-RES-20 title: GNSS spoofing / jamming resilience test (authorised) --- -AUTHORISED, RF-shielded / conducted testing only — never radiate GNSS over the air. Generate a synthetic GNSS scenario (e.g. with gps-sdr-sim) and transmit it on a TX-capable SDR (HackRF / bladeRF / USRP) into a shielded enclosure or a cabled setup, then observe whether the receiver under test locks onto the false position, follows a slow position / time pull-off from the genuine fix, or detects and rejects the attack. Test jamming resilience separately with a controlled in-band noise source. Assess any anti-spoofing the receiver claims (RAIM, signal-authentication, multi-constellation cross-checks). +AUTHORISED, RF-shielded / conducted testing only, never radiate GNSS over the air. Generate a synthetic GNSS scenario (e.g. with gps-sdr-sim) and transmit it on a TX-capable SDR (HackRF / bladeRF / USRP) into a shielded enclosure or a cabled setup, then observe whether the receiver under test locks onto the false position, follows a slow position / time pull-off from the genuine fix, or detects and rejects the attack. Test jamming resilience separately with a controlled in-band noise source. Assess any anti-spoofing the receiver claims (RAIM, signal-authentication, multi-constellation cross-checks). diff --git a/src/content/resources/rfsam-res-21.md b/src/content/resources/rfsam-res-21.md index 98c3578..4585b72 100644 --- a/src/content/resources/rfsam-res-21.md +++ b/src/content/resources/rfsam-res-21.md @@ -2,4 +2,4 @@ id: RFSAM-RES-21 title: Capture and decode ADS-B (1090ES / 978 UAT) --- -ADS-B is broadcast and unencrypted. Receive 1090 MHz Mode S Extended Squitter (1090ES, PPM) on an RTL-SDR and decode with dump1090 or readsb to recover the ICAO 24-bit address, callsign, altitude and position from the DF17/DF18 messages; in the US, decode the 978 MHz UAT link with dump978. There is no crypto to break — the security property of interest is the *absence* of authentication or integrity, which is what makes injection/spoofing possible (and is assessed, authorised and RF-contained, at the Attack step). +ADS-B is broadcast and unencrypted. Receive 1090 MHz Mode S Extended Squitter (1090ES, PPM) on an RTL-SDR and decode with dump1090 or readsb to recover the ICAO 24-bit address, callsign, altitude and position from the DF17/DF18 messages; in the US, decode the 978 MHz UAT link with dump978. There is no crypto to break, the security property of interest is the *absence* of authentication or integrity, which is what makes injection/spoofing possible (and is assessed, authorised and RF-contained, at the Attack step). diff --git a/src/content/resources/rfsam-res-22.md b/src/content/resources/rfsam-res-22.md index ecc55ae..eb856fa 100644 --- a/src/content/resources/rfsam-res-22.md +++ b/src/content/resources/rfsam-res-22.md @@ -2,4 +2,4 @@ id: RFSAM-RES-22 title: Identify and capture a 5G NR cell --- -Find the 5G NR carrier and its SS/PBCH block (SSB) on a waterfall — FR1 sub-6 GHz is reachable with a USRP-class SDR, while FR2 mmWave (~24–40 GHz) is out of reach of the common kit. There is no drop-in passive SA receiver: the practical routes are to stand up your own gNB (srsRAN Project or OpenAirInterface) with a 5G core and read the SSB / MIB / SIB1 from a controlled cell, to use a research PDCCH/MAC sniffer (5GSniffer / Sni5Gect) on a USRP, or to pull signalling off a Qualcomm 5G modem's DIAG interface with QCSuper into Wireshark. Note the SUCI conceals the SUPI, so the LTE-style cleartext-IMSI harvest is closed. +Find the 5G NR carrier and its SS/PBCH block (SSB) on a waterfall, FR1 sub-6 GHz is reachable with a USRP-class SDR, while FR2 mmWave (~24 to 40 GHz) is out of reach of the common kit. There is no drop-in passive SA receiver: the practical routes are to stand up your own gNB (srsRAN Project or OpenAirInterface) with a 5G core and read the SSB / MIB / SIB1 from a controlled cell, to use a research PDCCH/MAC sniffer (5GSniffer / Sni5Gect) on a USRP, or to pull signalling off a Qualcomm 5G modem's DIAG interface with QCSuper into Wireshark. Note the SUCI conceals the SUPI, so the LTE-style cleartext-IMSI harvest is closed. diff --git a/src/content/resources/rfsam-res-23.md b/src/content/resources/rfsam-res-23.md index 77010b1..1d00dd0 100644 --- a/src/content/resources/rfsam-res-23.md +++ b/src/content/resources/rfsam-res-23.md @@ -2,4 +2,4 @@ id: RFSAM-RES-23 title: Survey and capture a GSM cell (ARFCN → GSMTAP) --- -Scan a GSM band (850 / 900 / 1800 / 1900) for live base-station carriers with kalibrate, which locks onto each BTS's FCCH/SCH bursts and reports the ARFCN, its power and the radio's ppm clock offset. Tune the target ARFCN on an SDR and demodulate with gr-gsm (grgsm_livemon): it decodes the BCCH/CCCH/SDCCH bursts and streams GSMTAP over UDP into Wireshark, where you read the System Information, paging and the Cipher Mode Command — confirming the A5/x cipher in force and whether the cell exposes the IMSI. Easiest on a non-hopping downlink. +Scan a GSM band (850 / 900 / 1800 / 1900) for live base-station carriers with kalibrate, which locks onto each BTS's FCCH/SCH bursts and reports the ARFCN, its power and the radio's ppm clock offset. Tune the target ARFCN on an SDR and demodulate with gr-gsm (grgsm_livemon): it decodes the BCCH/CCCH/SDCCH bursts and streams GSMTAP over UDP into Wireshark, where you read the System Information, paging and the Cipher Mode Command, confirming the A5/x cipher in force and whether the cell exposes the IMSI. Easiest on a non-hopping downlink. diff --git a/src/content/resources/rfsam-res-24.md b/src/content/resources/rfsam-res-24.md index f501c53..0c25595 100644 --- a/src/content/resources/rfsam-res-24.md +++ b/src/content/resources/rfsam-res-24.md @@ -2,4 +2,4 @@ id: RFSAM-RES-24 title: Capture UWB 802.15.4z ranging exchanges --- -UWB cannot be blind-scanned and no SDR in the common kit reaches its >500 MHz-wide channels at 6.5 GHz (ch 5) / 8 GHz (ch 9). Capture 802.15.4z frames with a real UWB transceiver that already knows the link's channel, preamble code, data rate and STS mode/length: a Qorvo DWM3000EVB running the SEEMOO uwb-sniffer firmware forwards frames to Wireshark with picosecond timestamps, and a controllable DW3000 peer (Makerfabs board / foldedtoad driver) logs the ranging exchanges it participates in. Capturing the frames does not defeat the STS — the research surface is physical-layer distance manipulation, not key recovery. +UWB cannot be blind-scanned and no SDR in the common kit reaches its >500 MHz-wide channels at 6.5 GHz (ch 5) / 8 GHz (ch 9). Capture 802.15.4z frames with a real UWB transceiver that already knows the link's channel, preamble code, data rate and STS mode/length: a Qorvo DWM3000EVB running the SEEMOO uwb-sniffer firmware forwards frames to Wireshark with picosecond timestamps, and a controllable DW3000 peer (Makerfabs board / foldedtoad driver) logs the ranging exchanges it participates in. Capturing the frames does not defeat the STS, the research surface is physical-layer distance manipulation, not key recovery. diff --git a/src/content/resources/rfsam-res-25.md b/src/content/resources/rfsam-res-25.md index e1719e5..c665565 100644 --- a/src/content/resources/rfsam-res-25.md +++ b/src/content/resources/rfsam-res-25.md @@ -2,4 +2,4 @@ id: RFSAM-RES-25 title: Capture Bluetooth Classic BR/EDR baseband on a cheap ESP32 --- -An SDR cannot follow Bluetooth Classic's adaptive frequency hopping (~1600 hops/s across 79 channels), so the accessible BR/EDR capture path borrows a device that already owns a real Bluetooth controller. Matheus-Garbelini's `esp32_bluetooth_classic_sniffer` patches the ESP32's Bluetooth ROM stack so the chip dumps the baseband packets it already demodulates — BT header, channel, role, FHS, ACL and LMP — over USB serial to a Python host tool (`BTSnifferBREDR.py`) that emits Scapy objects and a live Wireshark feed, all on a ~$5–10 board (the original ESP32, not an S3/C-series, which lack the Classic radio). The catch is that it is an active sniffer: it joins the piconet and connects to the target to follow the hop rather than capturing purely passively, so it is for authorised testing on devices you own or are contracted to assess. It is the most practical commodity-hardware alternative to expensive BR/EDR test gear, though coverage and stability vary by target chip and it is no substitute for a calibrated protocol analyser. Pair it with Wireshark for dissection of the exported frames. +An SDR cannot follow Bluetooth Classic's adaptive frequency hopping (~1600 hops/s across 79 channels), so the accessible BR/EDR capture path borrows a device that already owns a real Bluetooth controller. Matheus-Garbelini's `esp32_bluetooth_classic_sniffer` patches the ESP32's Bluetooth ROM stack so the chip dumps the baseband packets it already demodulates, BT header, channel, role, FHS, ACL and LMP, over USB serial to a Python host tool (`BTSnifferBREDR.py`) that emits Scapy objects and a live Wireshark feed, all on a ~$5 to 10 board (the original ESP32, not an S3/C-series, which lack the Classic radio). The catch is that it is an active sniffer: it joins the piconet and connects to the target to follow the hop rather than capturing purely passively, so it is for authorised testing on devices you own or are contracted to assess. It is the most practical commodity-hardware alternative to expensive BR/EDR test gear, though coverage and stability vary by target chip and it is no substitute for a calibrated protocol analyser. Pair it with Wireshark for dissection of the exported frames. diff --git a/src/content/resources/rfsam-res-26.md b/src/content/resources/rfsam-res-26.md index 4b83e8d..5ccc677 100644 --- a/src/content/resources/rfsam-res-26.md +++ b/src/content/resources/rfsam-res-26.md @@ -2,4 +2,4 @@ id: RFSAM-RES-26 title: Inquiry-scan Bluetooth Classic devices with an ESP32 --- -The BR/EDR analogue of a BLE advertising scan is an inquiry scan, and an ESP32 can run a real one using its own Bluetooth Classic controller through the Bluedroid GAP API — no SDR required. AntorFr's `ClassicBTScan` and esp32beans's `ESP32-BT-exp` (a dual-mode Classic + BLE scanner) both bring up the stack and enumerate each discoverable device's 48-bit BD_ADDR, friendly name, RSSI and Class of Device, which together hint at the device type before any deeper RF work. This only sees devices currently in discoverable / inquiry-scan mode; a non-discoverable device will not answer and must already be addressed by a known BD_ADDR. It also requires the original ESP32 with the BR/EDR radio — the ESP32-S3 and C-series are LE-only and cannot run Classic inquiry. Treat it as the cheap "is anything Classic here, and what is it?" enumeration step that feeds the rest of the descent. +The BR/EDR analogue of a BLE advertising scan is an inquiry scan, and an ESP32 can run a real one using its own Bluetooth Classic controller through the Bluedroid GAP API, no SDR required. AntorFr's `ClassicBTScan` and esp32beans's `ESP32-BT-exp` (a dual-mode Classic + BLE scanner) both bring up the stack and enumerate each discoverable device's 48-bit BD_ADDR, friendly name, RSSI and Class of Device, which together hint at the device type before any deeper RF work. This only sees devices currently in discoverable / inquiry-scan mode; a non-discoverable device will not answer and must already be addressed by a known BD_ADDR. It also requires the original ESP32 with the BR/EDR radio, the ESP32-S3 and C-series are LE-only and cannot run Classic inquiry. Treat it as the cheap "is anything Classic here, and what is it?" enumeration step that feeds the rest of the descent. diff --git a/src/content/resources/rfsam-res-27.md b/src/content/resources/rfsam-res-27.md index e52c161..70e5e6d 100644 --- a/src/content/resources/rfsam-res-27.md +++ b/src/content/resources/rfsam-res-27.md @@ -2,4 +2,4 @@ id: RFSAM-RES-27 title: 'BrakTooth: fuzzing Bluetooth Classic baseband and LMP' --- -BrakTooth (Garbelini et al., ASSET Research Group, SUTD, 2021) is a directed-fuzzing campaign against the Bluetooth Classic Link Manager Protocol and baseband that found a family of implementation flaws — 16 vulnerabilities plus several anomalous behaviours, spanning 20+ exploit variants — across BR/EDR controllers from many SoC vendors (Espressif, Intel, Qualcomm, Texas Instruments and others). Effects range from crashes and deadlocks to, on at least one chip, arbitrary code execution, and most variants need neither pairing nor authentication to the target. The public proof-of-concept, Matheus-Garbelini's `braktooth_esp32_bluetooth_classic_attacks`, fires these malformed LMP/baseband sequences at a target from a cheap ESP32, reusing the same patched-firmware approach as the BR/EDR sniffer. Because these crash or deadlock live devices it is strictly for authorised testing on equipment you own or are contracted to assess. The CVE list and affected-SoC table are representative and date quickly — confirm current vendor patch status rather than trusting the original disclosure. +BrakTooth (Garbelini et al., ASSET Research Group, SUTD, 2021) is a directed-fuzzing campaign against the Bluetooth Classic Link Manager Protocol and baseband that found a family of implementation flaws, 16 vulnerabilities plus several anomalous behaviours, spanning 20+ exploit variants, across BR/EDR controllers from many SoC vendors (Espressif, Intel, Qualcomm, Texas Instruments and others). Effects range from crashes and deadlocks to, on at least one chip, arbitrary code execution, and most variants need neither pairing nor authentication to the target. The public proof-of-concept, Matheus-Garbelini's `braktooth_esp32_bluetooth_classic_attacks`, fires these malformed LMP/baseband sequences at a target from a cheap ESP32, reusing the same patched-firmware approach as the BR/EDR sniffer. Because these crash or deadlock live devices it is strictly for authorised testing on equipment you own or are contracted to assess. The CVE list and affected-SoC table are representative and date quickly, confirm current vendor patch status rather than trusting the original disclosure. diff --git a/src/content/resources/rfsam-res-28.md b/src/content/resources/rfsam-res-28.md index 44d373c..a7e32a9 100644 --- a/src/content/resources/rfsam-res-28.md +++ b/src/content/resources/rfsam-res-28.md @@ -2,4 +2,4 @@ id: RFSAM-RES-28 title: 'KNOB: downgrading Bluetooth encryption key entropy' --- -KNOB (Key Negotiation Of Bluetooth; Antonioli, Tippenhauer and Rasmussen, USENIX Security 2019; CVE-2019-9506) exploits the fact that the BR/EDR encryption key-length negotiation runs before encryption and is itself unauthenticated, letting an attacker in the middle force two victims to agree on an encryption key with as little as 1 byte (8 bits) of entropy. That key is then trivially brute-forced offline, after which the attacker can decrypt eavesdropped traffic and inject valid encrypted frames. It is a protocol-level downgrade against the specification — not a cryptographic break of E0 or AES-CCM — so it affected essentially every spec-compliant BR/EDR device of its era regardless of chip vendor. The mitigation is a host/controller-enforced minimum encryption key length (the Bluetooth SIG recommends rejecting keys below 7 octets), which closes the downgrade without touching the cipher. Performing it requires active man-in-the-middle injection during key negotiation, so it belongs only in authorised testing against devices you own or are contracted to assess. +KNOB (Key Negotiation Of Bluetooth; Antonioli, Tippenhauer and Rasmussen, USENIX Security 2019; CVE-2019-9506) exploits the fact that the BR/EDR encryption key-length negotiation runs before encryption and is itself unauthenticated, letting an attacker in the middle force two victims to agree on an encryption key with as little as 1 byte (8 bits) of entropy. That key is then trivially brute-forced offline, after which the attacker can decrypt eavesdropped traffic and inject valid encrypted frames. It is a protocol-level downgrade against the specification, not a cryptographic break of E0 or AES-CCM, so it affected essentially every spec-compliant BR/EDR device of its era regardless of chip vendor. The mitigation is a host/controller-enforced minimum encryption key length (the Bluetooth SIG recommends rejecting keys below 7 octets), which closes the downgrade without touching the cipher. Performing it requires active man-in-the-middle injection during key negotiation, so it belongs only in authorised testing against devices you own or are contracted to assess. diff --git a/src/content/resources/rfsam-res-29.md b/src/content/resources/rfsam-res-29.md index da01eb6..0b30c48 100644 --- a/src/content/resources/rfsam-res-29.md +++ b/src/content/resources/rfsam-res-29.md @@ -2,4 +2,4 @@ id: RFSAM-RES-29 title: Enumerate Bluetooth Classic services with BlueZ --- -The supported way to map the BR/EDR application surface is a normal Linux host running the BlueZ stack over any standard USB Bluetooth adapter — the same host path the BSAM Bluetooth controls assume. Start with `sdptool browse ` to walk the device's SDP service directory and list its exposed profiles and RFCOMM channels, use `l2ping ` to confirm reachability, and drive `bluetoothctl` to pair and connect. From there, profile-specific tools exercise what the device trusts above the link: `obexftp` for OBEX object push/pull, and HID/HFP utilities to probe keystroke-injection or hands-free/AT-command surfaces over RFCOMM. This is a legitimate host stack, not a covert injector, so most of it requires the target to be reachable and usually pairable — discoverability, pairing mode and service access control all gate what you can enumerate. It needs no special radio beyond a working BlueZ-supported dongle, which makes it the cheapest and most reproducible entry point into the Classic application layer. +The supported way to map the BR/EDR application surface is a normal Linux host running the BlueZ stack over any standard USB Bluetooth adapter, the same host path the BSAM Bluetooth controls assume. Start with `sdptool browse ` to walk the device's SDP service directory and list its exposed profiles and RFCOMM channels, use `l2ping ` to confirm reachability, and drive `bluetoothctl` to pair and connect. From there, profile-specific tools exercise what the device trusts above the link: `obexftp` for OBEX object push/pull, and HID/HFP utilities to probe keystroke-injection or hands-free/AT-command surfaces over RFCOMM. This is a legitimate host stack, not a covert injector, so most of it requires the target to be reachable and usually pairable, discoverability, pairing mode and service access control all gate what you can enumerate. It needs no special radio beyond a working BlueZ-supported dongle, which makes it the cheapest and most reproducible entry point into the Classic application layer. diff --git a/src/content/tools/5greplay.md b/src/content/tools/5greplay.md index d5f66ad..fb593fd 100644 --- a/src/content/tools/5greplay.md +++ b/src/content/tools/5greplay.md @@ -10,9 +10,9 @@ homepage: 'https://5greplay.org' note: >- 5G network-traffic fuzzer and replay engine (built on Montimage's MMT). Takes captured 5G control-/data-plane traffic, lets you write rules to modify - fields, and replays the altered packets — online or offline — toward a target + fields, and replays the altered packets, online or offline, toward a target 5G component (AMF/SMF over NGAP/SCTP, or a gNB) for protocol fuzzing and attack-injection testing. Operates on traffic, not radio: it consumes a capture (e.g. from Wireshark) and a target core, no SDR. --- -5G network-traffic fuzzer and replay engine (built on Montimage's MMT). Takes captured 5G control-/data-plane traffic, lets you write rules to modify fields, and replays the altered packets — online or offline — toward a target 5G component (AMF/SMF over NGAP/SCTP, or a gNB) for protocol fuzzing and attack-injection testing. Operates on traffic, not radio: it consumes a capture (e.g. from Wireshark) and a target core, no SDR. +5G network-traffic fuzzer and replay engine (built on Montimage's MMT). Takes captured 5G control-/data-plane traffic, lets you write rules to modify fields, and replays the altered packets, online or offline, toward a target 5G component (AMF/SMF over NGAP/SCTP, or a gNB) for protocol fuzzing and attack-injection testing. Operates on traffic, not radio: it consumes a capture (e.g. from Wireshark) and a target core, no SDR. diff --git a/src/content/tools/5gsniffer.md b/src/content/tools/5gsniffer.md index e637889..32291bc 100644 --- a/src/content/tools/5gsniffer.md +++ b/src/content/tools/5gsniffer.md @@ -10,8 +10,8 @@ note: >- Open-source 5G NR Physical Downlink Control Channel (PDCCH) blind decoder: passively recovers the Downlink Control Information (DCI) and the RNTIs active in a cell, exposing scheduling/identity activity for traffic analysis. Written - in C++ on srsRAN libraries; FDD, FR1 sub-6 GHz. Research-grade — the current + in C++ on srsRAN libraries; FDD, FR1 sub-6 GHz. Research-grade, the current release recommends working from a recorded I/Q file rather than live SDR, and live capture needs extra setup. --- -Open-source 5G NR Physical Downlink Control Channel (PDCCH) blind decoder: passively recovers the Downlink Control Information (DCI) and the RNTIs active in a cell, exposing scheduling/identity activity for traffic analysis. Written in C++ on srsRAN libraries; FDD, FR1 sub-6 GHz. Research-grade — the current release recommends working from a recorded I/Q file rather than live SDR, and live capture needs extra setup. +Open-source 5G NR Physical Downlink Control Channel (PDCCH) blind decoder: passively recovers the Downlink Control Information (DCI) and the RNTIs active in a cell, exposing scheduling/identity activity for traffic analysis. Written in C++ on srsRAN libraries; FDD, FR1 sub-6 GHz. Research-grade, the current release recommends working from a recorded I/Q file rather than live SDR, and live capture needs extra setup. diff --git a/src/content/tools/acr122u.md b/src/content/tools/acr122u.md index 8307be4..f8aabf4 100644 --- a/src/content/tools/acr122u.md +++ b/src/content/tools/acr122u.md @@ -8,9 +8,9 @@ protocols: - RFID homepage: 'https://github.com/nfc-tools/libnfc/wiki' note: >- - Cheap USB 13.56 MHz HF reader (ACR122U / PN532 breakout) — the standard libnfc + Cheap USB 13.56 MHz HF reader (ACR122U / PN532 breakout), the standard libnfc target for reading and dumping ISO 14443-A MIFARE cards and for running the mfoc/mfcuk crackers. HF only; no LF, and weaker than a Proxmark for adversarial work. --- -Cheap USB 13.56 MHz HF reader (ACR122U / PN532 breakout) — the standard libnfc target for reading and dumping ISO 14443-A MIFARE cards and for running the mfoc/mfcuk crackers. HF only; no LF, and weaker than a Proxmark for adversarial work. +Cheap USB 13.56 MHz HF reader (ACR122U / PN532 breakout), the standard libnfc target for reading and dumping ISO 14443-A MIFARE cards and for running the mfoc/mfcuk crackers. HF only; no LF, and weaker than a Proxmark for adversarial work. diff --git a/src/content/tools/adsb-out.md b/src/content/tools/adsb-out.md index 51c2089..f742b4b 100644 --- a/src/content/tools/adsb-out.md +++ b/src/content/tools/adsb-out.md @@ -10,10 +10,10 @@ note: >- A Python encoder that builds forged 1090ES ADS-B Extended Squitter frames (chosen ICAO address, position, altitude) into an I/Q sample file for transmission by a TX-capable SDR (HackRF via hackrf_transfer). The concrete - way to demonstrate ADS-B spoofing/injection — there is no authentication on + way to demonstrate ADS-B spoofing/injection, there is no authentication on the link, so a higher-power forged frame is accepted as a real aircraft. Author states it is for academic purposes only. AUTHORIZED, RF-CONTAINED - testing only: never radiate on-air — use a shielded enclosure or a conducted + testing only: never radiate on-air, use a shielded enclosure or a conducted (cabled) setup. Stable but inactive (last commit ~2021). --- -A Python encoder that builds forged 1090ES ADS-B Extended Squitter frames (chosen ICAO address, position, altitude) into an I/Q sample file for transmission by a TX-capable SDR (HackRF via hackrf_transfer). The concrete way to demonstrate ADS-B spoofing/injection — there is no authentication on the link, so a higher-power forged frame is accepted as a real aircraft. Author states it is for academic purposes only. AUTHORIZED, RF-CONTAINED testing only: never radiate on-air — use a shielded enclosure or a conducted (cabled) setup. Stable but inactive (last commit ~2021). +A Python encoder that builds forged 1090ES ADS-B Extended Squitter frames (chosen ICAO address, position, altitude) into an I/Q sample file for transmission by a TX-capable SDR (HackRF via hackrf_transfer). The concrete way to demonstrate ADS-B spoofing/injection, there is no authentication on the link, so a higher-power forged frame is accepted as a real aircraft. Author states it is for academic purposes only. AUTHORIZED, RF-CONTAINED testing only: never radiate on-air, use a shielded enclosure or a conducted (cabled) setup. Stable but inactive (last commit ~2021). diff --git a/src/content/tools/alfa-awus036ach.md b/src/content/tools/alfa-awus036ach.md index d8b13d3..2af2162 100644 --- a/src/content/tools/alfa-awus036ach.md +++ b/src/content/tools/alfa-awus036ach.md @@ -11,7 +11,7 @@ software: - bettercap - wireshark note: >- - RTL8812AU dual-band Wi-Fi adapter with monitor mode and injection — the + RTL8812AU dual-band Wi-Fi adapter with monitor mode and injection, the workhorse 802.11 capture/injection radio for surveys and handshake capture. --- -RTL8812AU dual-band Wi-Fi adapter with monitor mode and injection — the workhorse 802.11 capture/injection radio for surveys and handshake capture. +RTL8812AU dual-band Wi-Fi adapter with monitor mode and injection, the workhorse 802.11 capture/injection radio for surveys and handshake capture. diff --git a/src/content/tools/apimote.md b/src/content/tools/apimote.md index ab83ea5..76dd43e 100644 --- a/src/content/tools/apimote.md +++ b/src/content/tools/apimote.md @@ -11,8 +11,8 @@ software: - killerbee note: >- IEEE 802.15.4 / Zigbee sniffing-and-injection hardware (CC2420-based) built as - the reference KillerBee radio — it can both capture and transmit frames, which + the reference KillerBee radio, it can both capture and transmit frames, which makes it the go-to board for KillerBee's active and attack tools (zbreplay, zbstumbler). --- -IEEE 802.15.4 / Zigbee sniffing-and-injection hardware (CC2420-based) built as the reference KillerBee radio — it can both capture and transmit frames, which makes it the go-to board for KillerBee's active and attack tools (zbreplay, zbstumbler). +IEEE 802.15.4 / Zigbee sniffing-and-injection hardware (CC2420-based) built as the reference KillerBee radio, it can both capture and transmit frames, which makes it the go-to board for KillerBee's active and attack tools (zbreplay, zbstumbler). diff --git a/src/content/tools/applejuice.md b/src/content/tools/applejuice.md index cdf7117..eb5c47a 100644 --- a/src/content/tools/applejuice.md +++ b/src/content/tools/applejuice.md @@ -8,9 +8,9 @@ protocols: repo: 'https://github.com/ECTO-1A/AppleJuice' note: >- The original Apple BLE proximity-pairing message-spoofing research/PoC (~1.9k - stars, Apache-2.0, last push 2024-06) — the upstream source of the 'Apple BLE + stars, Apache-2.0, last push 2024-06), the upstream source of the 'Apple BLE spam' payloads reused by Marauder, Bruce, Ghost ESP and EvilAppleJuice. A reference corpus rather than a polished tool; payloads date as Apple patches, so treat as representative, not current. --- -The original Apple BLE proximity-pairing message-spoofing research/PoC (~1.9k stars, Apache-2.0, last push 2024-06) — the upstream source of the 'Apple BLE spam' payloads reused by Marauder, Bruce, Ghost ESP and EvilAppleJuice. A reference corpus rather than a polished tool; payloads date as Apple patches, so treat as representative, not current. +The original Apple BLE proximity-pairing message-spoofing research/PoC (~1.9k stars, Apache-2.0, last push 2024-06), the upstream source of the 'Apple BLE spam' payloads reused by Marauder, Bruce, Ghost ESP and EvilAppleJuice. A reference corpus rather than a polished tool; payloads date as Apple patches, so treat as representative, not current. diff --git a/src/content/tools/bbc-microbit.md b/src/content/tools/bbc-microbit.md index a16b7f8..9bb0620 100644 --- a/src/content/tools/bbc-microbit.md +++ b/src/content/tools/bbc-microbit.md @@ -9,7 +9,7 @@ homepage: 'https://microbit.org' software: - btlejack note: >- - A ~$15 nRF51822 board — the reference cheap radio for running Btlejack to + A ~$15 nRF51822 board, the reference cheap radio for running Btlejack to sniff, jam and hijack BLE connections. --- -A ~$15 nRF51822 board — the reference cheap radio for running Btlejack to sniff, jam and hijack BLE connections. +A ~$15 nRF51822 board, the reference cheap radio for running Btlejack to sniff, jam and hijack BLE connections. diff --git a/src/content/tools/bladerf-2-micro.md b/src/content/tools/bladerf-2-micro.md index 8c33b29..97ae68f 100644 --- a/src/content/tools/bladerf-2-micro.md +++ b/src/content/tools/bladerf-2-micro.md @@ -5,14 +5,14 @@ vendor: Nuand type: hardware protocols: - Wide-band SDR -spec: 56 MHz IBW · up to 122.88 MHz oversampled (8-bit) · 47 MHz–6 GHz +spec: 56 MHz IBW · up to 122.88 MHz oversampled (8-bit) · 47 MHz to 6 GHz homepage: 'https://www.nuand.com/2023-02-release-122-88mhz-bandwidth/' software: - ice9-bluetooth-sniffer note: >- Wideband full-duplex SDR (AD9361). ~56 MHz standard, and since the 2023.02 release an oversampling mode reaches 122.88 MHz instantaneous bandwidth (at - 8-bit depth over USB 3.0) — enough to cover the entire 80 MHz BLE band in a + 8-bit depth over USB 3.0), enough to cover the entire 80 MHz BLE band in a single pass. --- -Wideband full-duplex SDR (AD9361). ~56 MHz standard, and since the 2023.02 release an oversampling mode reaches 122.88 MHz instantaneous bandwidth (at 8-bit depth over USB 3.0) — enough to cover the entire 80 MHz BLE band in a single pass. +Wideband full-duplex SDR (AD9361). ~56 MHz standard, and since the 2023.02 release an oversampling mode reaches 122.88 MHz instantaneous bandwidth (at 8-bit depth over USB 3.0), enough to cover the entire 80 MHz BLE band in a single pass. diff --git a/src/content/tools/braktooth.md b/src/content/tools/braktooth.md index d93fd65..e26ce4f 100644 --- a/src/content/tools/braktooth.md +++ b/src/content/tools/braktooth.md @@ -8,11 +8,11 @@ protocols: repo: 'https://github.com/Matheus-Garbelini/braktooth_esp32_bluetooth_classic_attacks' note: >- The public PoC release for the BrakTooth family of Bluetooth Classic - baseband/LMP vulnerabilities — roughly 16 CVEs and 20+ attack variants against + baseband/LMP vulnerabilities, roughly 16 CVEs and 20+ attack variants against the BR/EDR controllers of dozens of SoCs (Espressif ESP32, Intel AX200, Qualcomm, Cypress/Infineon, TI CC2564 and more). Built on the patched-ESP32 sniffer; the attacks range from crash/DoS to, on some targets, RCE. - Representative — check vendor advisories for current patch status. Authorised + Representative, check vendor advisories for current patch status. Authorised testing only, against devices you own or are contracted to assess. --- -The public PoC release for the BrakTooth family of Bluetooth Classic baseband/LMP vulnerabilities — roughly 16 CVEs and 20+ attack variants against the BR/EDR controllers of dozens of SoCs (Espressif ESP32, Intel AX200, Qualcomm, Cypress/Infineon, TI CC2564 and more). Built on the patched-ESP32 sniffer; the attacks range from crash/DoS to, on some targets, RCE. Representative — check vendor advisories for current patch status. Authorised testing only, against devices you own or are contracted to assess. +The public PoC release for the BrakTooth family of Bluetooth Classic baseband/LMP vulnerabilities, roughly 16 CVEs and 20+ attack variants against the BR/EDR controllers of dozens of SoCs (Espressif ESP32, Intel AX200, Qualcomm, Cypress/Infineon, TI CC2564 and more). Built on the patched-ESP32 sniffer; the attacks range from crash/DoS to, on some targets, RCE. Representative, check vendor advisories for current patch status. Authorised testing only, against devices you own or are contracted to assess. diff --git a/src/content/tools/cc2531.md b/src/content/tools/cc2531.md index 10b20a0..c69e2c7 100644 --- a/src/content/tools/cc2531.md +++ b/src/content/tools/cc2531.md @@ -12,7 +12,7 @@ software: - whsniff - kismet note: >- - Cheap TI CC2531 USB dongle flashed with packet-sniffer firmware — a 2.4 GHz + Cheap TI CC2531 USB dongle flashed with packet-sniffer firmware, a 2.4 GHz 802.15.4 capture-only radio (no injection). Bridged to Wireshark by whsniff. --- -Cheap TI CC2531 USB dongle flashed with packet-sniffer firmware — a 2.4 GHz 802.15.4 capture-only radio (no injection). Bridged to Wireshark by whsniff. +Cheap TI CC2531 USB dongle flashed with packet-sniffer firmware, a 2.4 GHz 802.15.4 capture-only radio (no injection). Bridged to Wireshark by whsniff. diff --git a/src/content/tools/chip-repl.md b/src/content/tools/chip-repl.md index cc23f0a..7bf8758 100644 --- a/src/content/tools/chip-repl.md +++ b/src/content/tools/chip-repl.md @@ -12,8 +12,8 @@ note: >- The Python Matter controller and interactive REPL from the connectedhomeip SDK (src/controller/python, matter-repl.py). Same native CHIP device-controller stack as chip-tool but scriptable: stand up a fabric, commission over BLE, - then read/subscribe/write attributes and invoke cluster commands from Python — + then read/subscribe/write attributes and invoke cluster commands from Python, convenient for automating commissioning-attack and cluster-enumeration workflows and for multi-fabric tests. --- -The Python Matter controller and interactive REPL from the connectedhomeip SDK (src/controller/python, matter-repl.py). Same native CHIP device-controller stack as chip-tool but scriptable: stand up a fabric, commission over BLE, then read/subscribe/write attributes and invoke cluster commands from Python — convenient for automating commissioning-attack and cluster-enumeration workflows and for multi-fabric tests. +The Python Matter controller and interactive REPL from the connectedhomeip SDK (src/controller/python, matter-repl.py). Same native CHIP device-controller stack as chip-tool but scriptable: stand up a fabric, commission over BLE, then read/subscribe/write attributes and invoke cluster commands from Python, convenient for automating commissioning-attack and cluster-enumeration workflows and for multi-fabric tests. diff --git a/src/content/tools/chip-tool.md b/src/content/tools/chip-tool.md index 11b3403..17929fe 100644 --- a/src/content/tools/chip-tool.md +++ b/src/content/tools/chip-tool.md @@ -10,12 +10,12 @@ protocols: repo: 'https://github.com/project-chip/connectedhomeip' note: >- The Matter controller/commissioner CLI from the connectedhomeip SDK - (examples/chip-tool). Commissions a Matter device over Bluetooth LE — + (examples/chip-tool). Commissions a Matter device over Bluetooth LE, establishing a PASE (SPAKE2+) session from the setup passcode, handing over Thread/Wi-Fi credentials with `pairing ble-thread` / `pairing ble-wifi` (or - `pairing onnetwork` / `pairing code` once on-network) — then drives it with + `pairing onnetwork` / `pairing code` once on-network), then drives it with CASE-secured operational commands. Also opens a second commissioning window (`pairing open-commissioning-window`) to test multi-admin. The tool for assessing Matter onboarding and the application-layer cluster interface. --- -The Matter controller/commissioner CLI from the connectedhomeip SDK (examples/chip-tool). Commissions a Matter device over Bluetooth LE — establishing a PASE (SPAKE2+) session from the setup passcode, handing over Thread/Wi-Fi credentials with `pairing ble-thread` / `pairing ble-wifi` (or `pairing onnetwork` / `pairing code` once on-network) — then drives it with CASE-secured operational commands. Also opens a second commissioning window (`pairing open-commissioning-window`) to test multi-admin. The tool for assessing Matter onboarding and the application-layer cluster interface. +The Matter controller/commissioner CLI from the connectedhomeip SDK (examples/chip-tool). Commissions a Matter device over Bluetooth LE, establishing a PASE (SPAKE2+) session from the setup passcode, handing over Thread/Wi-Fi credentials with `pairing ble-thread` / `pairing ble-wifi` (or `pairing onnetwork` / `pairing code` once on-network), then drives it with CASE-secured operational commands. Also opens a second commissioning window (`pairing open-commissioning-window`) to test multi-admin. The tool for assessing Matter onboarding and the application-layer cluster interface. diff --git a/src/content/tools/chirpcat.md b/src/content/tools/chirpcat.md index a640542..aaa620b 100644 --- a/src/content/tools/chirpcat.md +++ b/src/content/tools/chirpcat.md @@ -9,10 +9,10 @@ protocols: repo: 'https://github.com/ElectronicCats/chirpcat' note: >- LoRa/LoRaWAN discovery, classification and capture platform. Listens to - LoRaWAN traffic — both uplink and downlink frames — through a gateway backend + LoRaWAN traffic, both uplink and downlink frames, through a gateway backend (Semtech UDP packet forwarder on port 1700), clusters packets by RF characteristics, scores/classifies targets and dispatches follow/capture tasks to CatSniffer workers. Designed to run on the RAK WisGate Connect (Raspberry Pi CM4). --- -LoRa/LoRaWAN discovery, classification and capture platform. Listens to LoRaWAN traffic — both uplink and downlink frames — through a gateway backend (Semtech UDP packet forwarder on port 1700), clusters packets by RF characteristics, scores/classifies targets and dispatches follow/capture tasks to CatSniffer workers. Designed to run on the RAK WisGate Connect (Raspberry Pi CM4). +LoRa/LoRaWAN discovery, classification and capture platform. Listens to LoRaWAN traffic, both uplink and downlink frames, through a gateway backend (Semtech UDP packet forwarder on port 1700), clusters packets by RF characteristics, scores/classifies targets and dispatches follow/capture tasks to CatSniffer workers. Designed to run on the RAK WisGate Connect (Raspberry Pi CM4). diff --git a/src/content/tools/chirpstack.md b/src/content/tools/chirpstack.md index a9a6c15..f575b06 100644 --- a/src/content/tools/chirpstack.md +++ b/src/content/tools/chirpstack.md @@ -11,8 +11,8 @@ repo: 'https://github.com/chirpstack/chirpstack' note: >- Open-source LoRaWAN Network Server stack (gateway bridge, network server, application server). Provides the network-server side a replay or fuzzing - attack is staged against — stand up a ChirpStack instance to model the + attack is staged against, stand up a ChirpStack instance to model the target's server and observe how it handles replayed, forged or malformed frames. --- -Open-source LoRaWAN Network Server stack (gateway bridge, network server, application server). Provides the network-server side a replay or fuzzing attack is staged against — stand up a ChirpStack instance to model the target's server and observe how it handles replayed, forged or malformed frames. +Open-source LoRaWAN Network Server stack (gateway bridge, network server, application server). Provides the network-server side a replay or fuzzing attack is staged against, stand up a ChirpStack instance to model the target's server and observe how it handles replayed, forged or malformed frames. diff --git a/src/content/tools/connectedhomeip.md b/src/content/tools/connectedhomeip.md index 96c1c4a..3d782a0 100644 --- a/src/content/tools/connectedhomeip.md +++ b/src/content/tools/connectedhomeip.md @@ -11,7 +11,7 @@ repo: 'https://github.com/project-chip/connectedhomeip' note: >- The official open-source Matter (formerly Project CHIP) SDK from the Connectivity Standards Alliance. Provides the device stack, example apps and - the chip-tool controller — the reference codebase for building and exercising + the chip-tool controller, the reference codebase for building and exercising Matter-over-Thread and Matter-over-Wi-Fi nodes and their commissioning. --- -The official open-source Matter (formerly Project CHIP) SDK from the Connectivity Standards Alliance. Provides the device stack, example apps and the chip-tool controller — the reference codebase for building and exercising Matter-over-Thread and Matter-over-Wi-Fi nodes and their commissioning. +The official open-source Matter (formerly Project CHIP) SDK from the Connectivity Standards Alliance. Provides the device stack, example apps and the chip-tool controller, the reference codebase for building and exercising Matter-over-Thread and Matter-over-Wi-Fi nodes and their commissioning. diff --git a/src/content/tools/cyd.md b/src/content/tools/cyd.md index 015de3c..4ff1bf8 100644 --- a/src/content/tools/cyd.md +++ b/src/content/tools/cyd.md @@ -1,6 +1,6 @@ --- slug: cyd -name: CYD — Cheap Yellow Display (ESP32-2432S028R) +name: CYD, Cheap Yellow Display (ESP32-2432S028R) vendor: community (Witnessmenow guide) type: hardware protocols: @@ -16,8 +16,8 @@ software: note: >- The ~$15 'Cheap Yellow Display': an ESP32-WROOM-32 board with a built-in 2.8" touch TFT, microSD and USB-UART. Hugely popular as a cheap touchscreen pentest - handheld — runs ESP32 Marauder (and CYD-specific forks), Bruce and Ghost ESP + handheld, runs ESP32 Marauder (and CYD-specific forks), Bruce and Ghost ESP with a usable on-screen UI and no soldering. The linked repo is the community hardware/pinout reference. --- -The ~$15 'Cheap Yellow Display': an ESP32-WROOM-32 board with a built-in 2.8" touch TFT, microSD and USB-UART. Hugely popular as a cheap touchscreen pentest handheld — runs ESP32 Marauder (and CYD-specific forks), Bruce and Ghost ESP with a usable on-screen UI and no soldering. The linked repo is the community hardware/pinout reference. +The ~$15 'Cheap Yellow Display': an ESP32-WROOM-32 board with a built-in 2.8" touch TFT, microSD and USB-UART. Hugely popular as a cheap touchscreen pentest handheld, runs ESP32 Marauder (and CYD-specific forks), Bruce and Ghost ESP with a usable on-screen UI and no soldering. The linked repo is the community hardware/pinout reference. diff --git a/src/content/tools/dwm3000-dwt-driver.md b/src/content/tools/dwm3000-dwt-driver.md index e1f40d3..82fb2f7 100644 --- a/src/content/tools/dwm3000-dwt-driver.md +++ b/src/content/tools/dwm3000-dwt-driver.md @@ -11,7 +11,7 @@ note: >- dwt_uwb_driver API) to the DWS3000 Arduino shield, runnable under Zephyr. The practical glue for bringing up a DW3000 board, configuring its 802.15.4z PHY parameters (channel, preamble, PRF, STS mode), and running two-way-ranging - exchanges you can log — the dev-board path for capturing/characterising + exchanges you can log, the dev-board path for capturing/characterising ranging behaviour. A development driver, not an attack tool. --- -An open port of Qorvo/Decawave's DWM3000 driver and ranging examples (the dwt_uwb_driver API) to the DWS3000 Arduino shield, runnable under Zephyr. The practical glue for bringing up a DW3000 board, configuring its 802.15.4z PHY parameters (channel, preamble, PRF, STS mode), and running two-way-ranging exchanges you can log — the dev-board path for capturing/characterising ranging behaviour. A development driver, not an attack tool. +An open port of Qorvo/Decawave's DWM3000 driver and ranging examples (the dwt_uwb_driver API) to the DWS3000 Arduino shield, runnable under Zephyr. The practical glue for bringing up a DW3000 board, configuring its 802.15.4z PHY parameters (channel, preamble, PRF, STS mode), and running two-way-ranging exchanges you can log, the dev-board path for capturing/characterising ranging behaviour. A development driver, not an attack tool. diff --git a/src/content/tools/dwm3000evb.md b/src/content/tools/dwm3000evb.md index 8e96d68..9a18268 100644 --- a/src/content/tools/dwm3000evb.md +++ b/src/content/tools/dwm3000evb.md @@ -18,8 +18,7 @@ note: >- second-generation impulse-radio transceiver) on an Arduino form factor. Designed against the FiRa PHY/MAC and interoperable with Apple's U1 & U2 chips, on channels 5 (6.5 GHz) and 9 (8 GHz). Drive it from a host MCU (e.g. a - NUCLEO-F429ZI or nRF52840) to range, log or — with the SEEMOO sniffer firmware - — capture 802.15.4z frames. The same board (a ~$65 EVB + nRF52DK) was the + NUCLEO-F429ZI or nRF52840) to range, log or, with the SEEMOO sniffer firmware, capture 802.15.4z frames. The same board (a ~$65 EVB + nRF52DK) was the attack platform in the Ghost Peak research. --- -The reference DW3000-family UWB development shield: a DWM3000 module (DW3110 second-generation impulse-radio transceiver) on an Arduino form factor. Designed against the FiRa PHY/MAC and interoperable with Apple's U1 & U2 chips, on channels 5 (6.5 GHz) and 9 (8 GHz). Drive it from a host MCU (e.g. a NUCLEO-F429ZI or nRF52840) to range, log or — with the SEEMOO sniffer firmware — capture 802.15.4z frames. The same board (a ~$65 EVB + nRF52DK) was the attack platform in the Ghost Peak research. +The reference DW3000-family UWB development shield: a DWM3000 module (DW3110 second-generation impulse-radio transceiver) on an Arduino form factor. Designed against the FiRa PHY/MAC and interoperable with Apple's U1 & U2 chips, on channels 5 (6.5 GHz) and 9 (8 GHz). Drive it from a host MCU (e.g. a NUCLEO-F429ZI or nRF52840) to range, log or, with the SEEMOO sniffer firmware, capture 802.15.4z frames. The same board (a ~$65 EVB + nRF52DK) was the attack platform in the Ghost Peak research. diff --git a/src/content/tools/esp32-airtag-scanner.md b/src/content/tools/esp32-airtag-scanner.md index 0cf8f12..0c237aa 100644 --- a/src/content/tools/esp32-airtag-scanner.md +++ b/src/content/tools/esp32-airtag-scanner.md @@ -9,8 +9,8 @@ repo: 'https://github.com/MatthewKuKanich/ESP32-AirTag-Scanner' note: >- ESP32 firmware that scans for Apple AirTag / Find My MAC addresses and BLE payloads without an Android phone or nRF Connect (~110 stars, last push - 2024-04). Passive scan only — no spoofing or emulation; output over UART. + 2024-04). Passive scan only, no spoofing or emulation; output over UART. Supports ESP32-WROOM and ESP32-S3. Useful at the survey step to detect trackers in the environment. --- -ESP32 firmware that scans for Apple AirTag / Find My MAC addresses and BLE payloads without an Android phone or nRF Connect (~110 stars, last push 2024-04). Passive scan only — no spoofing or emulation; output over UART. Supports ESP32-WROOM and ESP32-S3. Useful at the survey step to detect trackers in the environment. +ESP32 firmware that scans for Apple AirTag / Find My MAC addresses and BLE payloads without an Android phone or nRF Connect (~110 stars, last push 2024-04). Passive scan only, no spoofing or emulation; output over UART. Supports ESP32-WROOM and ESP32-S3. Useful at the survey step to detect trackers in the environment. diff --git a/src/content/tools/esp32-bluejammer.md b/src/content/tools/esp32-bluejammer.md index 8e0346a..64a2526 100644 --- a/src/content/tools/esp32-bluejammer.md +++ b/src/content/tools/esp32-bluejammer.md @@ -12,8 +12,8 @@ note: >- An ESP32 driving two nRF24L01+PA+LNA modules to flood the 2.4 GHz ISM band with noise, hopping channels to disrupt Bluetooth Classic (79 ch), BLE (40 ch), Wi-Fi (14 ch) and 2.4 GHz RC/drone links. WARNING: RF jamming is illegal - in most jurisdictions (e.g. unlawful in the US under FCC rules) — use only in + in most jurisdictions (e.g. unlawful in the US under FCC rules), use only in an RF-shielded / controlled environment for authorised resilience testing. Requires two nRF24L01+PA+LNA modules in addition to the ESP32. --- -An ESP32 driving two nRF24L01+PA+LNA modules to flood the 2.4 GHz ISM band with noise, hopping channels to disrupt Bluetooth Classic (79 ch), BLE (40 ch), Wi-Fi (14 ch) and 2.4 GHz RC/drone links. WARNING: RF jamming is illegal in most jurisdictions (e.g. unlawful in the US under FCC rules) — use only in an RF-shielded / controlled environment for authorised resilience testing. Requires two nRF24L01+PA+LNA modules in addition to the ESP32. +An ESP32 driving two nRF24L01+PA+LNA modules to flood the 2.4 GHz ISM band with noise, hopping channels to disrupt Bluetooth Classic (79 ch), BLE (40 ch), Wi-Fi (14 ch) and 2.4 GHz RC/drone links. WARNING: RF jamming is illegal in most jurisdictions (e.g. unlawful in the US under FCC rules), use only in an RF-shielded / controlled environment for authorised resilience testing. Requires two nRF24L01+PA+LNA modules in addition to the ESP32. diff --git a/src/content/tools/esp32-bt-classic-sniffer.md b/src/content/tools/esp32-bt-classic-sniffer.md index 4eed4fb..7f0615f 100644 --- a/src/content/tools/esp32-bt-classic-sniffer.md +++ b/src/content/tools/esp32-bt-classic-sniffer.md @@ -7,11 +7,11 @@ protocols: - Bluetooth Classic repo: 'https://github.com/Matheus-Garbelini/esp32_bluetooth_classic_sniffer' note: >- - The reference active BR/EDR sniffer on commodity ESP32 hardware (~$4–10; ~590 + The reference active BR/EDR sniffer on commodity ESP32 hardware (~$4 to 10; ~590 stars, GPL-2.0). It patches the ESP32 ROM Bluetooth stack to dump baseband - packets — BT header, channel, device role, FHS, ACL and LMP — over USB serial + packets, BT header, channel, device role, FHS, ACL and LMP, over USB serial to a host Python tool (BTSnifferBREDR.py) with Scapy/Wireshark output. This is Bluetooth CLASSIC (BR/EDR), not BLE. It actively connects to the target, so authorised testing only. --- -The reference active BR/EDR sniffer on commodity ESP32 hardware (~$4–10; ~590 stars, GPL-2.0). It patches the ESP32 ROM Bluetooth stack to dump baseband packets — BT header, channel, device role, FHS, ACL and LMP — over USB serial to a host Python tool (BTSnifferBREDR.py) with Scapy/Wireshark output. This is Bluetooth CLASSIC (BR/EDR), not BLE. It actively connects to the target, so authorised testing only. +The reference active BR/EDR sniffer on commodity ESP32 hardware (~$4 to 10; ~590 stars, GPL-2.0). It patches the ESP32 ROM Bluetooth stack to dump baseband packets, BT header, channel, device role, FHS, ACL and LMP, over USB serial to a host Python tool (BTSnifferBREDR.py) with Scapy/Wireshark output. This is Bluetooth CLASSIC (BR/EDR), not BLE. It actively connects to the target, so authorised testing only. diff --git a/src/content/tools/esp32-bt-exp.md b/src/content/tools/esp32-bt-exp.md index ee15f45..aa60c9f 100644 --- a/src/content/tools/esp32-bt-exp.md +++ b/src/content/tools/esp32-bt-exp.md @@ -10,7 +10,7 @@ repo: 'https://github.com/esp32beans/ESP32-BT-exp' note: >- An Arduino-ESP32 sketch that brings up the Bluedroid stack in dual-mode (Classic + BLE) and dumps discovered devices in pairing/inquiry mode (MIT). - Discovery only — no pairing or connection. Classic (BR/EDR) discovery needs + Discovery only, no pairing or connection. Classic (BR/EDR) discovery needs the original ESP32, not the C-series, which has no Bluetooth Classic radio. --- -An Arduino-ESP32 sketch that brings up the Bluedroid stack in dual-mode (Classic + BLE) and dumps discovered devices in pairing/inquiry mode (MIT). Discovery only — no pairing or connection. Classic (BR/EDR) discovery needs the original ESP32, not the C-series, which has no Bluetooth Classic radio. +An Arduino-ESP32 sketch that brings up the Bluedroid stack in dual-mode (Classic + BLE) and dumps discovered devices in pairing/inquiry mode (MIT). Discovery only, no pairing or connection. Classic (BR/EDR) discovery needs the original ESP32, not the C-series, which has no Bluetooth Classic radio. diff --git a/src/content/tools/esp32-classic-bt-scan.md b/src/content/tools/esp32-classic-bt-scan.md index 327ac33..5b0292f 100644 --- a/src/content/tools/esp32-classic-bt-scan.md +++ b/src/content/tools/esp32-classic-bt-scan.md @@ -8,9 +8,9 @@ protocols: repo: 'https://github.com/AntorFr/ClassicBTScan' note: >- A small Arduino-ESP32 library that performs a true Bluetooth Classic (BR/EDR) - inquiry scan via the Bluedroid GAP API — returning each discovered device's + inquiry scan via the Bluedroid GAP API, returning each discovered device's MAC address, name, RSSI and Class-of-Device (CoD). The BR/EDR analogue of a BLE advertising scan (MIT, last push 2020). Only finds devices in discoverable / inquiry-scan mode; pin it to a known ESP-IDF as it is unmaintained. --- -A small Arduino-ESP32 library that performs a true Bluetooth Classic (BR/EDR) inquiry scan via the Bluedroid GAP API — returning each discovered device's MAC address, name, RSSI and Class-of-Device (CoD). The BR/EDR analogue of a BLE advertising scan (MIT, last push 2020). Only finds devices in discoverable / inquiry-scan mode; pin it to a known ESP-IDF as it is unmaintained. +A small Arduino-ESP32 library that performs a true Bluetooth Classic (BR/EDR) inquiry scan via the Bluedroid GAP API, returning each discovered device's MAC address, name, RSSI and Class-of-Device (CoD). The BR/EDR analogue of a BLE advertising scan (MIT, last push 2020). Only finds devices in discoverable / inquiry-scan mode; pin it to a known ESP-IDF as it is unmaintained. diff --git a/src/content/tools/esp32-deauther-ganesh.md b/src/content/tools/esp32-deauther-ganesh.md index c044eff..72ac142 100644 --- a/src/content/tools/esp32-deauther-ganesh.md +++ b/src/content/tools/esp32-deauther-ganesh.md @@ -8,10 +8,10 @@ protocols: repo: 'https://github.com/GANESH-ICMC/esp32-deauther' note: >- An ESP-IDF port of the Spacehuhn deauther to the ESP32, built on the - esp_wifi_80211_tx frame-injection function — the canonical bare-ESP32 deauth + esp_wifi_80211_tx frame-injection function, the canonical bare-ESP32 deauth path referenced by risinek's penetration tool. NOTE: unmaintained since 2021 and ships no license file; confirm it builds against a current ESP-IDF before relying on it. (The famous Spacehuhn esp8266_deauther is ESP8266-only and does not run on the ESP32.) --- -An ESP-IDF port of the Spacehuhn deauther to the ESP32, built on the esp_wifi_80211_tx frame-injection function — the canonical bare-ESP32 deauth path referenced by risinek's penetration tool. NOTE: unmaintained since 2021 and ships no license file; confirm it builds against a current ESP-IDF before relying on it. (The famous Spacehuhn esp8266_deauther is ESP8266-only and does not run on the ESP32.) +An ESP-IDF port of the Spacehuhn deauther to the ESP32, built on the esp_wifi_80211_tx frame-injection function, the canonical bare-ESP32 deauth path referenced by risinek's penetration tool. NOTE: unmaintained since 2021 and ships no license file; confirm it builds against a current ESP-IDF before relying on it. (The famous Spacehuhn esp8266_deauther is ESP8266-only and does not run on the ESP32.) diff --git a/src/content/tools/esp32-devkit.md b/src/content/tools/esp32-devkit.md index 0deca54..788ba9a 100644 --- a/src/content/tools/esp32-devkit.md +++ b/src/content/tools/esp32-devkit.md @@ -20,11 +20,11 @@ software: - braktooth - esp32-bluejammer note: >- - The generic original ESP32 dev board (WROOM-32 / WROVER module) — the cheapest + The generic original ESP32 dev board (WROOM-32 / WROVER module), the cheapest substrate for the umbrella firmwares (Marauder, Bruce, Ghost ESP) and the bare-metal Wi-Fi/BLE tools. Crucially, the ORIGINAL ESP32 is the only variant with a Bluetooth Classic (BR/EDR) radio, so it is also the board the BR/EDR - sniffer and BrakTooth PoC run on. A bare board with no screen or SD — add a + sniffer and BrakTooth PoC run on. A bare board with no screen or SD, add a microSD for capture-to-card firmwares. 2.4 GHz only (no 5/6 GHz). --- -The generic original ESP32 dev board (WROOM-32 / WROVER module) — the cheapest substrate for the umbrella firmwares (Marauder, Bruce, Ghost ESP) and the bare-metal Wi-Fi/BLE tools. Crucially, the ORIGINAL ESP32 is the only variant with a Bluetooth Classic (BR/EDR) radio, so it is also the board the BR/EDR sniffer and BrakTooth PoC run on. A bare board with no screen or SD — add a microSD for capture-to-card firmwares. 2.4 GHz only (no 5/6 GHz). +The generic original ESP32 dev board (WROOM-32 / WROVER module), the cheapest substrate for the umbrella firmwares (Marauder, Bruce, Ghost ESP) and the bare-metal Wi-Fi/BLE tools. Crucially, the ORIGINAL ESP32 is the only variant with a Bluetooth Classic (BR/EDR) radio, so it is also the board the BR/EDR sniffer and BrakTooth PoC run on. A bare board with no screen or SD, add a microSD for capture-to-card firmwares. 2.4 GHz only (no 5/6 GHz). diff --git a/src/content/tools/esp32-marauder.md b/src/content/tools/esp32-marauder.md index 5381858..dac83c1 100644 --- a/src/content/tools/esp32-marauder.md +++ b/src/content/tools/esp32-marauder.md @@ -14,7 +14,7 @@ note: >- SD, and an Evil Portal captive-portal credential harvester. BLE: scan/sniff, wardrive, AirTag sniff and spoof, and advertising spam (Apple/Sour Apple, Samsung, Swift Pair). Runs on ESP32/S2/S3/C5 and 20+ boards (Cardputer, CYD, - Flipper Wi-Fi dev board) — but NOT the ESP32-C6. 2.4 GHz only. Representative - of the ESP32 attack surface — authorised testing only on active features. + Flipper Wi-Fi dev board), but NOT the ESP32-C6. 2.4 GHz only. Representative + of the ESP32 attack surface, authorised testing only on active features. --- -The reference ESP32 Wi-Fi + BLE offensive/defensive firmware (~11k stars, actively maintained). Wi-Fi: scan APs/stations, packet sniff, GPS wardrive, deauth, beacon spam (list/random), probe-request flood, EAPOL/PMKID capture to SD, and an Evil Portal captive-portal credential harvester. BLE: scan/sniff, wardrive, AirTag sniff and spoof, and advertising spam (Apple/Sour Apple, Samsung, Swift Pair). Runs on ESP32/S2/S3/C5 and 20+ boards (Cardputer, CYD, Flipper Wi-Fi dev board) — but NOT the ESP32-C6. 2.4 GHz only. Representative of the ESP32 attack surface — authorised testing only on active features. +The reference ESP32 Wi-Fi + BLE offensive/defensive firmware (~11k stars, actively maintained). Wi-Fi: scan APs/stations, packet sniff, GPS wardrive, deauth, beacon spam (list/random), probe-request flood, EAPOL/PMKID capture to SD, and an Evil Portal captive-portal credential harvester. BLE: scan/sniff, wardrive, AirTag sniff and spoof, and advertising spam (Apple/Sour Apple, Samsung, Swift Pair). Runs on ESP32/S2/S3/C5 and 20+ boards (Cardputer, CYD, Flipper Wi-Fi dev board), but NOT the ESP32-C6. 2.4 GHz only. Representative of the ESP32 attack surface, authorised testing only on active features. diff --git a/src/content/tools/esp32-projectzero.md b/src/content/tools/esp32-projectzero.md index bebd27b..a09e004 100644 --- a/src/content/tools/esp32-projectzero.md +++ b/src/content/tools/esp32-projectzero.md @@ -10,8 +10,8 @@ note: >- A two-board ESP32 evil-twin / deauther whose captive portal VERIFIES the entered password against the real AP, plus a WPA3-SAE overflow mode (MIT, active but small/early). Runs on ESP32 and ESP32-C5, driven from a CLI or a - Flipper Zero. Low-maturity project — verify its behaviour on the bench before + Flipper Zero. Low-maturity project, verify its behaviour on the bench before field use; the password-verifying portal and SAE-overflow angle are what make it worth noting. --- -A two-board ESP32 evil-twin / deauther whose captive portal VERIFIES the entered password against the real AP, plus a WPA3-SAE overflow mode (MIT, active but small/early). Runs on ESP32 and ESP32-C5, driven from a CLI or a Flipper Zero. Low-maturity project — verify its behaviour on the bench before field use; the password-verifying portal and SAE-overflow angle are what make it worth noting. +A two-board ESP32 evil-twin / deauther whose captive portal VERIFIES the entered password against the real AP, plus a WPA3-SAE overflow mode (MIT, active but small/early). Runs on ESP32 and ESP32-C5, driven from a CLI or a Flipper Zero. Low-maturity project, verify its behaviour on the bench before field use; the password-verifying portal and SAE-overflow angle are what make it worth noting. diff --git a/src/content/tools/esp32-s3-devkit.md b/src/content/tools/esp32-s3-devkit.md index e1fb9bf..4912dd2 100644 --- a/src/content/tools/esp32-s3-devkit.md +++ b/src/content/tools/esp32-s3-devkit.md @@ -17,10 +17,10 @@ software: - esp32-airtag-scanner note: >- Espressif's ESP32-S3: LX7 dual-core with Bluetooth 5 (LE), native USB-OTG and - more RAM than the original ESP32 — which is why most modern handheld pentest + more RAM than the original ESP32, which is why most modern handheld pentest boards (Cardputer, LilyGo T-series) are S3-based. Supported by Marauder, Bruce and Ghost ESP, and the BLE-capable target for the focused BLE tools. Note: the - S3 has BLE but NO Bluetooth Classic radio — for BR/EDR work use the original + S3 has BLE but NO Bluetooth Classic radio, for BR/EDR work use the original ESP32. --- -Espressif's ESP32-S3: LX7 dual-core with Bluetooth 5 (LE), native USB-OTG and more RAM than the original ESP32 — which is why most modern handheld pentest boards (Cardputer, LilyGo T-series) are S3-based. Supported by Marauder, Bruce and Ghost ESP, and the BLE-capable target for the focused BLE tools. Note: the S3 has BLE but NO Bluetooth Classic radio — for BR/EDR work use the original ESP32. +Espressif's ESP32-S3: LX7 dual-core with Bluetooth 5 (LE), native USB-OTG and more RAM than the original ESP32, which is why most modern handheld pentest boards (Cardputer, LilyGo T-series) are S3-based. Supported by Marauder, Bruce and Ghost ESP, and the BLE-capable target for the focused BLE tools. Note: the S3 has BLE but NO Bluetooth Classic radio, for BR/EDR work use the original ESP32. diff --git a/src/content/tools/esp32-sour-apple.md b/src/content/tools/esp32-sour-apple.md index e96fdd8..f2d4a55 100644 --- a/src/content/tools/esp32-sour-apple.md +++ b/src/content/tools/esp32-sour-apple.md @@ -9,8 +9,8 @@ repo: 'https://github.com/RapierXbox/ESP32-Sour-Apple' note: >- A focused PoC that crashes/freezes iOS devices by flooding them with BLE pairing-request advertisements (~595 stars, GPL-3.0). Tested on ESP32-S3 and - ESP-WROOM-32 (an ESP8266 cannot run it — no BLE radio). Genuinely disruptive — - it can freeze nearby iPhones — so authorised testing only, on hardware you + ESP-WROOM-32 (an ESP8266 cannot run it, no BLE radio). Genuinely disruptive, + it can freeze nearby iPhones, so authorised testing only, on hardware you own. Target/payload effectiveness dates as Apple patches. --- -A focused PoC that crashes/freezes iOS devices by flooding them with BLE pairing-request advertisements (~595 stars, GPL-3.0). Tested on ESP32-S3 and ESP-WROOM-32 (an ESP8266 cannot run it — no BLE radio). Genuinely disruptive — it can freeze nearby iPhones — so authorised testing only, on hardware you own. Target/payload effectiveness dates as Apple patches. +A focused PoC that crashes/freezes iOS devices by flooding them with BLE pairing-request advertisements (~595 stars, GPL-3.0). Tested on ESP32-S3 and ESP-WROOM-32 (an ESP8266 cannot run it, no BLE radio). Genuinely disruptive, it can freeze nearby iPhones, so authorised testing only, on hardware you own. Target/payload effectiveness dates as Apple patches. diff --git a/src/content/tools/esp32-wifi-penetration-tool.md b/src/content/tools/esp32-wifi-penetration-tool.md index 4452640..9099fe2 100644 --- a/src/content/tools/esp32-wifi-penetration-tool.md +++ b/src/content/tools/esp32-wifi-penetration-tool.md @@ -11,8 +11,8 @@ note: >- 2024-02). Captures WPA/WPA2 PMKIDs and 4-way handshakes (passively, via a rogue duplicate AP, or by forcing re-auth), formats captures to PCAP and converts them to a hashcat-ready HCCAPX; also runs deauthentication and DoS - attacks. Driven entirely from an on-device management-AP web UI — no screen + attacks. Driven entirely from an on-device management-AP web UI, no screen needed. Includes a WSL bypasser to emit arbitrary 802.11 frames on a plain ESP32. --- -Focused ESP-IDF framework for ESP32 Wi-Fi attacks (~2.9k stars, MIT, last push 2024-02). Captures WPA/WPA2 PMKIDs and 4-way handshakes (passively, via a rogue duplicate AP, or by forcing re-auth), formats captures to PCAP and converts them to a hashcat-ready HCCAPX; also runs deauthentication and DoS attacks. Driven entirely from an on-device management-AP web UI — no screen needed. Includes a WSL bypasser to emit arbitrary 802.11 frames on a plain ESP32. +Focused ESP-IDF framework for ESP32 Wi-Fi attacks (~2.9k stars, MIT, last push 2024-02). Captures WPA/WPA2 PMKIDs and 4-way handshakes (passively, via a rogue duplicate AP, or by forcing re-auth), formats captures to PCAP and converts them to a hashcat-ready HCCAPX; also runs deauthentication and DoS attacks. Driven entirely from an on-device management-AP web UI, no screen needed. Includes a WSL bypasser to emit arbitrary 802.11 frames on a plain ESP32. diff --git a/src/content/tools/evilapplejuice-esp32.md b/src/content/tools/evilapplejuice-esp32.md index a3dfe53..19995e5 100644 --- a/src/content/tools/evilapplejuice-esp32.md +++ b/src/content/tools/evilapplejuice-esp32.md @@ -7,10 +7,9 @@ protocols: - BLE repo: 'https://github.com/ckcr4lyf/EvilAppleJuice-ESP32' note: >- - A self-contained ESP32 sketch that spams Apple BLE proximity-pairing messages - — the 'connect AirPods / setup' style popups — on nearby iOS devices (~2.1k + A self-contained ESP32 sketch that spams Apple BLE proximity-pairing messages, the 'connect AirPods / setup' style popups, on nearby iOS devices (~2.1k stars). Single-purpose Apple advertising spam, derived from the AppleJuice proximity-spoof research. Authorised testing only; disruptive to all nearby Apple devices. --- -A self-contained ESP32 sketch that spams Apple BLE proximity-pairing messages — the 'connect AirPods / setup' style popups — on nearby iOS devices (~2.1k stars). Single-purpose Apple advertising spam, derived from the AppleJuice proximity-spoof research. Authorised testing only; disruptive to all nearby Apple devices. +A self-contained ESP32 sketch that spams Apple BLE proximity-pairing messages, the 'connect AirPods / setup' style popups, on nearby iOS devices (~2.1k stars). Single-purpose Apple advertising spam, derived from the AppleJuice proximity-spoof research. Authorised testing only; disruptive to all nearby Apple devices. diff --git a/src/content/tools/ez-wave.md b/src/content/tools/ez-wave.md index d7030cd..041074e 100644 --- a/src/content/tools/ez-wave.md +++ b/src/content/tools/ez-wave.md @@ -13,7 +13,7 @@ note: >- interrogates a device (manufacturer/model, firmware version, supported command classes, configuration), and ezfingerprint identifies the Z-Wave module generation via a PHY preamble-length manipulation. Default config drives two - HackRF One SDRs. Python 2.7 / GNU Radio 3.7 era — dated but still the + HackRF One SDRs. Python 2.7 / GNU Radio 3.7 era, dated but still the canonical exploitation toolkit. --- -The reference open Z-Wave assessment suite (GNU Radio + Scapy-radio): ezstumbler does passive discovery and active network enumeration, ezrecon interrogates a device (manufacturer/model, firmware version, supported command classes, configuration), and ezfingerprint identifies the Z-Wave module generation via a PHY preamble-length manipulation. Default config drives two HackRF One SDRs. Python 2.7 / GNU Radio 3.7 era — dated but still the canonical exploitation toolkit. +The reference open Z-Wave assessment suite (GNU Radio + Scapy-radio): ezstumbler does passive discovery and active network enumeration, ezrecon interrogates a device (manufacturer/model, firmware version, supported command classes, configuration), and ezfingerprint identifies the Z-Wave module generation via a PHY preamble-length manipulation. Default config drives two HackRF One SDRs. Python 2.7 / GNU Radio 3.7 era, dated but still the canonical exploitation toolkit. diff --git a/src/content/tools/falcon.md b/src/content/tools/falcon.md index e26ca18..bdfd128 100644 --- a/src/content/tools/falcon.md +++ b/src/content/tools/falcon.md @@ -7,8 +7,8 @@ protocols: - LTE repo: 'https://github.com/falkenber9/falcon' note: >- - Fast Analysis of LTE Control channels — built on srsRAN to blind-decode the + Fast Analysis of LTE Control channels, built on srsRAN to blind-decode the entire PDCCH in real time, exposing every DCI/RNTI scheduling grant in a cell. A passive view of live control-channel activity and resource usage. --- -Fast Analysis of LTE Control channels — built on srsRAN to blind-decode the entire PDCCH in real time, exposing every DCI/RNTI scheduling grant in a cell. A passive view of live control-channel activity and resource usage. +Fast Analysis of LTE Control channels, built on srsRAN to blind-decode the entire PDCCH in real time, exposing every DCI/RNTI scheduling grant in a cell. A passive view of live control-channel activity and resource usage. diff --git a/src/content/tools/flipper-wifi-devboard.md b/src/content/tools/flipper-wifi-devboard.md index 7af8e83..f0cdacb 100644 --- a/src/content/tools/flipper-wifi-devboard.md +++ b/src/content/tools/flipper-wifi-devboard.md @@ -5,7 +5,7 @@ vendor: Flipper Devices type: hardware protocols: - Wi-Fi -spec: ESP32-S2-WROVER · 2.4 GHz Wi-Fi only — S2 has NO Bluetooth radio +spec: ESP32-S2-WROVER · 2.4 GHz Wi-Fi only, S2 has NO Bluetooth radio homepage: 'https://flipper.net/products/wifi-devboard' software: - esp32-marauder @@ -14,6 +14,6 @@ note: >- firmware flashing / debugging, but the community flashes ESP32 Marauder onto it to give the Flipper a Wi-Fi attack add-on (deauth, beacon spam, Evil Portal). Because the S2 has no Bluetooth radio, the BLE features are NOT - available on this board — it is Wi-Fi only. + available on this board, it is Wi-Fi only. --- -Official Flipper Zero add-on built on an ESP32-S2-WROVER. Sold for wireless firmware flashing / debugging, but the community flashes ESP32 Marauder onto it to give the Flipper a Wi-Fi attack add-on (deauth, beacon spam, Evil Portal). Because the S2 has no Bluetooth radio, the BLE features are NOT available on this board — it is Wi-Fi only. +Official Flipper Zero add-on built on an ESP32-S2-WROVER. Sold for wireless firmware flashing / debugging, but the community flashes ESP32 Marauder onto it to give the Flipper a Wi-Fi attack add-on (deauth, beacon spam, Evil Portal). Because the S2 has no Bluetooth radio, the BLE features are NOT available on this board, it is Wi-Fi only. diff --git a/src/content/tools/flipper-zero.md b/src/content/tools/flipper-zero.md index 3b6bc1e..2b29d97 100644 --- a/src/content/tools/flipper-zero.md +++ b/src/content/tools/flipper-zero.md @@ -9,16 +9,16 @@ protocols: - NFC - Infrared spec: >- - CC1101 transceiver · RX/TX 300–348, 387–464 & 779–928 MHz · OOK/ASK + (G)FSK · + CC1101 transceiver · RX/TX 300 to 348, 387 to 464 & 779 to 928 MHz · OOK/ASK + (G)FSK · handheld homepage: 'https://flipper.net/' software: - flipperzero-firmware note: >- Handheld multitool whose built-in CC1101 transceiver receives and transmits - across the 300–348, 387–464 and 779–928 MHz sub-GHz bands — the everyday field + across the 300 to 348, 387 to 464 and 779 to 928 MHz sub-GHz bands, the everyday field radio for reading, saving and replaying garage/gate/doorbell remotes and other fixed-code devices, with no laptop or SDR. OOK/ASK and (G)FSK; its Read mode decodes known protocols and Read RAW captures unknown ones for later replay. --- -Handheld multitool whose built-in CC1101 transceiver receives and transmits across the 300–348, 387–464 and 779–928 MHz sub-GHz bands — the everyday field radio for reading, saving and replaying garage/gate/doorbell remotes and other fixed-code devices, with no laptop or SDR. OOK/ASK and (G)FSK; its Read mode decodes known protocols and Read RAW captures unknown ones for later replay. +Handheld multitool whose built-in CC1101 transceiver receives and transmits across the 300 to 348, 387 to 464 and 779 to 928 MHz sub-GHz bands, the everyday field radio for reading, saving and replaying garage/gate/doorbell remotes and other fixed-code devices, with no laptop or SDR. OOK/ASK and (G)FSK; its Read mode decodes known protocols and Read RAW captures unknown ones for later replay. diff --git a/src/content/tools/flipperzero-firmware.md b/src/content/tools/flipperzero-firmware.md index a74743a..266a43f 100644 --- a/src/content/tools/flipperzero-firmware.md +++ b/src/content/tools/flipperzero-firmware.md @@ -11,8 +11,8 @@ note: >- (decode a known protocol), Read RAW (capture an unknown signal as raw timings), Save and Send (replay/emulate a saved signal), and a manual virtual-remote builder. The official firmware deliberately refuses to save or - replay rolling-code signals (e.g. KeeLoq) as a built-in safety limit — + replay rolling-code signals (e.g. KeeLoq) as a built-in safety limit, capture-and-replay works on fixed-code devices, not rolling-code ones, on stock firmware. --- -The open-source firmware that runs the Flipper Zero's Sub-GHz app: Read (decode a known protocol), Read RAW (capture an unknown signal as raw timings), Save and Send (replay/emulate a saved signal), and a manual virtual-remote builder. The official firmware deliberately refuses to save or replay rolling-code signals (e.g. KeeLoq) as a built-in safety limit — capture-and-replay works on fixed-code devices, not rolling-code ones, on stock firmware. +The open-source firmware that runs the Flipper Zero's Sub-GHz app: Read (decode a known protocol), Read RAW (capture an unknown signal as raw timings), Save and Send (replay/emulate a saved signal), and a manual virtual-remote builder. The official firmware deliberately refuses to save or replay rolling-code signals (e.g. KeeLoq) as a built-in safety limit, capture-and-replay works on fixed-code devices, not rolling-code ones, on stock firmware. diff --git a/src/content/tools/forthink-uwb-dongle.md b/src/content/tools/forthink-uwb-dongle.md index 05eec4b..ab975c1 100644 --- a/src/content/tools/forthink-uwb-dongle.md +++ b/src/content/tools/forthink-uwb-dongle.md @@ -10,9 +10,9 @@ homepage: 'https://github.com/forthink-xyz/forthink_uwb_sniffer_tool' software: - forthink-uwb-sniffer note: >- - Forthink's commercial UWB-Dongle-Sniffer — a closed, purchased + Forthink's commercial UWB-Dongle-Sniffer, a closed, purchased FT4222H-interfaced UWB capture dongle (not open hardware). It is the radio the open Forthink sniffer software and Wireshark plugin run against; the dongle must be bought from Forthink. --- -Forthink's commercial UWB-Dongle-Sniffer — a closed, purchased FT4222H-interfaced UWB capture dongle (not open hardware). It is the radio the open Forthink sniffer software and Wireshark plugin run against; the dongle must be bought from Forthink. +Forthink's commercial UWB-Dongle-Sniffer, a closed, purchased FT4222H-interfaced UWB capture dongle (not open hardware). It is the radio the open Forthink sniffer software and Wireshark plugin run against; the dongle must be bought from Forthink. diff --git a/src/content/tools/forthink-uwb-sniffer.md b/src/content/tools/forthink-uwb-sniffer.md index 6d28fd9..238abfe 100644 --- a/src/content/tools/forthink-uwb-sniffer.md +++ b/src/content/tools/forthink-uwb-sniffer.md @@ -9,12 +9,12 @@ repo: 'https://github.com/forthink-xyz/forthink_uwb_sniffer_tool' note: >- Open-source host software and a Wireshark plugin (forthink-xyz/uwb-sniffer-wireshark) that monitor and decode CCC, FiRa and - IEEE 802.15.4a/z UWB — including parameters for Apple Car-Key and + IEEE 802.15.4a/z UWB, including parameters for Apple Car-Key and AirTag/Nearby-Interaction (FiRa) traffic. Caveat: the software is open but it REQUIRES Forthink's COMMERCIAL UWB-Dongle-Sniffer hardware (an - FT4222H-interfaced dongle) — the radio itself is a closed, purchased product, + FT4222H-interfaced dongle), the radio itself is a closed, purchased product, not open hardware. Listed for completeness as the most capable off-the-shelf UWB capture path; it observes frames, it does not defeat STS-protected ranging integrity. --- -Open-source host software and a Wireshark plugin (forthink-xyz/uwb-sniffer-wireshark) that monitor and decode CCC, FiRa and IEEE 802.15.4a/z UWB — including parameters for Apple Car-Key and AirTag/Nearby-Interaction (FiRa) traffic. Caveat: the software is open but it REQUIRES Forthink's COMMERCIAL UWB-Dongle-Sniffer hardware (an FT4222H-interfaced dongle) — the radio itself is a closed, purchased product, not open hardware. Listed for completeness as the most capable off-the-shelf UWB capture path; it observes frames, it does not defeat STS-protected ranging integrity. +Open-source host software and a Wireshark plugin (forthink-xyz/uwb-sniffer-wireshark) that monitor and decode CCC, FiRa and IEEE 802.15.4a/z UWB, including parameters for Apple Car-Key and AirTag/Nearby-Interaction (FiRa) traffic. Caveat: the software is open but it REQUIRES Forthink's COMMERCIAL UWB-Dongle-Sniffer hardware (an FT4222H-interfaced dongle), the radio itself is a closed, purchased product, not open hardware. Listed for completeness as the most capable off-the-shelf UWB capture path; it observes frames, it does not defeat STS-protected ranging integrity. diff --git a/src/content/tools/free5gc.md b/src/content/tools/free5gc.md index cd3eaf1..0fa23a3 100644 --- a/src/content/tools/free5gc.md +++ b/src/content/tools/free5gc.md @@ -9,10 +9,10 @@ spec: 3GPP R15 5G Core · AMF/SMF/UPF/AUSF/UDM repo: 'https://github.com/free5gc/free5gc' homepage: 'https://free5gc.org' note: >- - Open-source 3GPP Release-15 5G Core network in Go — AMF, SMF, UPF, AUSF, UDM, + Open-source 3GPP Release-15 5G Core network in Go, AMF, SMF, UPF, AUSF, UDM, NRF and the rest of the SBA. An alternative to Open5GS as the 5GC behind a test gNB (srsRAN/OAI): provision test subscribers, drive 5G-AKA authentication and the NAS-5GS registration procedures, and exercise NGAP between your gNB and core. Standalone (SA) only. --- -Open-source 3GPP Release-15 5G Core network in Go — AMF, SMF, UPF, AUSF, UDM, NRF and the rest of the SBA. An alternative to Open5GS as the 5GC behind a test gNB (srsRAN/OAI): provision test subscribers, drive 5G-AKA authentication and the NAS-5GS registration procedures, and exercise NGAP between your gNB and core. Standalone (SA) only. +Open-source 3GPP Release-15 5G Core network in Go, AMF, SMF, UPF, AUSF, UDM, NRF and the rest of the SBA. An alternative to Open5GS as the 5GC behind a test gNB (srsRAN/OAI): provision test subscribers, drive 5G-AKA authentication and the NAS-5GS registration procedures, and exercise NGAP between your gNB and core. Standalone (SA) only. diff --git a/src/content/tools/gnss-sdr.md b/src/content/tools/gnss-sdr.md index d921484..d3b190c 100644 --- a/src/content/tools/gnss-sdr.md +++ b/src/content/tools/gnss-sdr.md @@ -9,9 +9,9 @@ repo: 'https://github.com/gnss-sdr/gnss-sdr' homepage: 'https://gnss-sdr.org' note: >- Open-source software-defined GNSS receiver. Takes raw L-band I/Q from an SDR - and runs the full receive chain — acquisition, tracking, telemetry decoding of - the navigation message, and PVT (position/velocity/time) computation — for GPS + and runs the full receive chain, acquisition, tracking, telemetry decoding of + the navigation message, and PVT (position/velocity/time) computation, for GPS L1/L2/L5, Galileo, GLONASS and BeiDou. The reference way to receive and decode a live civilian GNSS signal in software. --- -Open-source software-defined GNSS receiver. Takes raw L-band I/Q from an SDR and runs the full receive chain — acquisition, tracking, telemetry decoding of the navigation message, and PVT (position/velocity/time) computation — for GPS L1/L2/L5, Galileo, GLONASS and BeiDou. The reference way to receive and decode a live civilian GNSS signal in software. +Open-source software-defined GNSS receiver. Takes raw L-band I/Q from an SDR and runs the full receive chain, acquisition, tracking, telemetry decoding of the navigation message, and PVT (position/velocity/time) computation, for GPS L1/L2/L5, Galileo, GLONASS and BeiDou. The reference way to receive and decode a live civilian GNSS signal in software. diff --git a/src/content/tools/gps-sdr-sim.md b/src/content/tools/gps-sdr-sim.md index 1c846db..443fca0 100644 --- a/src/content/tools/gps-sdr-sim.md +++ b/src/content/tools/gps-sdr-sim.md @@ -11,9 +11,9 @@ note: >- a chosen static or moving position, for transmission by an SDR (HackRF / bladeRF / USRP). Because civilian C/A is unauthenticated, a replayed/synthesised signal at higher power can pull a receiver's position and - clock to attacker-chosen values — the canonical GPS spoofing tool. AUTHORIZED, + clock to attacker-chosen values, the canonical GPS spoofing tool. AUTHORIZED, RF-CONTAINED testing only: transmitting GPS over the air is illegal in most - jurisdictions — use a shielded enclosure or a cabled (conducted) setup. Repo + jurisdictions, use a shielded enclosure or a cabled (conducted) setup. Repo is archived but remains the de-facto reference. --- -Generates a GPS L1 C/A baseband I/Q file from a RINEX broadcast ephemeris and a chosen static or moving position, for transmission by an SDR (HackRF / bladeRF / USRP). Because civilian C/A is unauthenticated, a replayed/synthesised signal at higher power can pull a receiver's position and clock to attacker-chosen values — the canonical GPS spoofing tool. AUTHORIZED, RF-CONTAINED testing only: transmitting GPS over the air is illegal in most jurisdictions — use a shielded enclosure or a cabled (conducted) setup. Repo is archived but remains the de-facto reference. +Generates a GPS L1 C/A baseband I/Q file from a RINEX broadcast ephemeris and a chosen static or moving position, for transmission by an SDR (HackRF / bladeRF / USRP). Because civilian C/A is unauthenticated, a replayed/synthesised signal at higher power can pull a receiver's position and clock to attacker-chosen values, the canonical GPS spoofing tool. AUTHORIZED, RF-CONTAINED testing only: transmitting GPS over the air is illegal in most jurisdictions, use a shielded enclosure or a cabled (conducted) setup. Repo is archived but remains the de-facto reference. diff --git a/src/content/tools/gpsd.md b/src/content/tools/gpsd.md index 04beb97..f2e0a6a 100644 --- a/src/content/tools/gpsd.md +++ b/src/content/tools/gpsd.md @@ -10,10 +10,10 @@ homepage: 'https://gpsd.io/' note: >- The GPS service daemon: it reads the NMEA 0183 / UBX stream from a GNSS receiver on a serial or USB port, parses it, and re-serves the solved - position/velocity/time to clients over a simple TCP/JSON protocol — with + position/velocity/time to clients over a simple TCP/JSON protocol, with gpsmon and cgps for live terminal display of the fix, satellites and raw sentences. The standard way to consume a real GPS receiver on Linux/BSD and the normal 'see what the receiver reports' tool. Hosted on GitLab/Savannah, not GitHub. --- -The GPS service daemon: it reads the NMEA 0183 / UBX stream from a GNSS receiver on a serial or USB port, parses it, and re-serves the solved position/velocity/time to clients over a simple TCP/JSON protocol — with gpsmon and cgps for live terminal display of the fix, satellites and raw sentences. The standard way to consume a real GPS receiver on Linux/BSD and the normal 'see what the receiver reports' tool. Hosted on GitLab/Savannah, not GitHub. +The GPS service daemon: it reads the NMEA 0183 / UBX stream from a GNSS receiver on a serial or USB port, parses it, and re-serves the solved position/velocity/time to clients over a simple TCP/JSON protocol, with gpsmon and cgps for live terminal display of the fix, satellites and raw sentences. The standard way to consume a real GPS receiver on Linux/BSD and the normal 'see what the receiver reports' tool. Hosted on GitLab/Savannah, not GitHub. diff --git a/src/content/tools/gqrx.md b/src/content/tools/gqrx.md index 744d7a8..95d8569 100644 --- a/src/content/tools/gqrx.md +++ b/src/content/tools/gqrx.md @@ -7,8 +7,8 @@ protocols: - any SDR repo: 'https://github.com/gqrx-sdr/gqrx' note: >- - Live spectrum + waterfall SDR receiver (HackRF, bladeRF, USRP…) — the quickest + Live spectrum + waterfall SDR receiver (HackRF, bladeRF, USRP…), the quickest way to see what is transmitting and where, and to judge how much of the band a given radio covers. --- -Live spectrum + waterfall SDR receiver (HackRF, bladeRF, USRP…) — the quickest way to see what is transmitting and where, and to judge how much of the band a given radio covers. +Live spectrum + waterfall SDR receiver (HackRF, bladeRF, USRP…), the quickest way to see what is transmitting and where, and to judge how much of the band a given radio covers. diff --git a/src/content/tools/gr-air-modes.md b/src/content/tools/gr-air-modes.md index 14e631c..db6e527 100644 --- a/src/content/tools/gr-air-modes.md +++ b/src/content/tools/gr-air-modes.md @@ -10,7 +10,7 @@ note: >- A GNU Radio Mode S / ADS-B receiver: a flowgraph that demodulates 1090 MHz and decodes the Extended Squitter, with a live map output. The choice when you want the signal inside a GNU Radio flowgraph to see and modify each DSP block - rather than a black-box decoder. Older codebase (last active ~2021) — a + rather than a black-box decoder. Older codebase (last active ~2021), a learning/DSP receiver rather than a polished aggregator. --- -A GNU Radio Mode S / ADS-B receiver: a flowgraph that demodulates 1090 MHz and decodes the Extended Squitter, with a live map output. The choice when you want the signal inside a GNU Radio flowgraph to see and modify each DSP block rather than a black-box decoder. Older codebase (last active ~2021) — a learning/DSP receiver rather than a polished aggregator. +A GNU Radio Mode S / ADS-B receiver: a flowgraph that demodulates 1090 MHz and decodes the Extended Squitter, with a live map output. The choice when you want the signal inside a GNU Radio flowgraph to see and modify each DSP block rather than a black-box decoder. Older codebase (last active ~2021), a learning/DSP receiver rather than a polished aggregator. diff --git a/src/content/tools/hackrf-one.md b/src/content/tools/hackrf-one.md index 2dddd40..9bf0ffa 100644 --- a/src/content/tools/hackrf-one.md +++ b/src/content/tools/hackrf-one.md @@ -5,14 +5,14 @@ vendor: Great Scott Gadgets type: hardware protocols: - Wide-band SDR -spec: ~20 MHz IBW · 1 MHz–6 GHz · half-duplex +spec: ~20 MHz IBW · 1 MHz to 6 GHz · half-duplex repo: 'https://github.com/greatscottgadgets/hackrf' software: - universal-radio-hacker - ice9-bluetooth-sniffer note: >- - 1 MHz–6 GHz half-duplex SDR — the discovery radio for 'Rapid Radio Reversing': + 1 MHz to 6 GHz half-duplex SDR, the discovery radio for 'Rapid Radio Reversing': find and characterise an unknown signal before working it with a narrowband tool. --- -1 MHz–6 GHz half-duplex SDR — the discovery radio for 'Rapid Radio Reversing': find and characterise an unknown signal before working it with a narrowband tool. +1 MHz to 6 GHz half-duplex SDR, the discovery radio for 'Rapid Radio Reversing': find and characterise an unknown signal before working it with a narrowband tool. diff --git a/src/content/tools/hashcat.md b/src/content/tools/hashcat.md index e51e10d..8b57162 100644 --- a/src/content/tools/hashcat.md +++ b/src/content/tools/hashcat.md @@ -9,6 +9,6 @@ repo: 'https://github.com/hashcat/hashcat' note: >- GPU-accelerated password recovery. For Wi-Fi, mode 22000 cracks both WPA/WPA2 4-way handshakes and PMKIDs from a .hc22000 hash using dictionary, rule and - mask attacks — the fastest offline WPA cracker. + mask attacks, the fastest offline WPA cracker. --- -GPU-accelerated password recovery. For Wi-Fi, mode 22000 cracks both WPA/WPA2 4-way handshakes and PMKIDs from a .hc22000 hash using dictionary, rule and mask attacks — the fastest offline WPA cracker. +GPU-accelerated password recovery. For Wi-Fi, mode 22000 cracks both WPA/WPA2 4-way handshakes and PMKIDs from a .hc22000 hash using dictionary, rule and mask attacks, the fastest offline WPA cracker. diff --git a/src/content/tools/hcxtools.md b/src/content/tools/hcxtools.md index 8ff281d..374cad5 100644 --- a/src/content/tools/hcxtools.md +++ b/src/content/tools/hcxtools.md @@ -8,7 +8,7 @@ protocols: repo: 'https://github.com/ZerBea/hcxtools' note: >- Companion converters for hcxdumptool captures. hcxpcapngtool turns a captured - pcapng into the hashcat/John .hc22000 hash format — the bridge from a raw + pcapng into the hashcat/John .hc22000 hash format, the bridge from a raw capture to an offline crack. --- -Companion converters for hcxdumptool captures. hcxpcapngtool turns a captured pcapng into the hashcat/John .hc22000 hash format — the bridge from a raw capture to an offline crack. +Companion converters for hcxdumptool captures. hcxpcapngtool turns a captured pcapng into the hashcat/John .hc22000 hash format, the bridge from a raw capture to an offline crack. diff --git a/src/content/tools/hostapd-mana.md b/src/content/tools/hostapd-mana.md index da4999c..27a7c2c 100644 --- a/src/content/tools/hostapd-mana.md +++ b/src/content/tools/hostapd-mana.md @@ -7,8 +7,8 @@ protocols: - Wi-Fi repo: 'https://github.com/sensepost/hostapd-mana' note: >- - SensePost's modified hostapd for Wi-Fi attacks — the 'MANA' rogue AP that + SensePost's modified hostapd for Wi-Fi attacks, the 'MANA' rogue AP that lures clients using their probe history and captures Enterprise/EAP credentials. The engine underneath EAPHammer. --- -SensePost's modified hostapd for Wi-Fi attacks — the 'MANA' rogue AP that lures clients using their probe history and captures Enterprise/EAP credentials. The engine underneath EAPHammer. +SensePost's modified hostapd for Wi-Fi attacks, the 'MANA' rogue AP that lures clients using their probe history and captures Enterprise/EAP credentials. The engine underneath EAPHammer. diff --git a/src/content/tools/ice9-bluetooth-sniffer.md b/src/content/tools/ice9-bluetooth-sniffer.md index fef3d31..ecccbbe 100644 --- a/src/content/tools/ice9-bluetooth-sniffer.md +++ b/src/content/tools/ice9-bluetooth-sniffer.md @@ -9,8 +9,8 @@ protocols: repo: 'https://github.com/mikeryan/ice9-bluetooth-sniffer' note: >- SDR-based, Wireshark-compatible all-channel sniffer (HackRF / bladeRF / USRP). - Unlike most sniffers it can sniff connections that are already established — + Unlike most sniffers it can sniff connections that are already established, invaluable when you cannot catch the connection request. Needs an SDR and GPU/CPU for channelisation. --- -SDR-based, Wireshark-compatible all-channel sniffer (HackRF / bladeRF / USRP). Unlike most sniffers it can sniff connections that are already established — invaluable when you cannot catch the connection request. Needs an SDR and GPU/CPU for channelisation. +SDR-based, Wireshark-compatible all-channel sniffer (HackRF / bladeRF / USRP). Unlike most sniffers it can sniff connections that are already established, invaluable when you cannot catch the connection request. Needs an SDR and GPU/CPU for channelisation. diff --git a/src/content/tools/imsi-catcher-srsran.md b/src/content/tools/imsi-catcher-srsran.md index 19edf17..aa6beb4 100644 --- a/src/content/tools/imsi-catcher-srsran.md +++ b/src/content/tools/imsi-catcher-srsran.md @@ -8,8 +8,8 @@ protocols: repo: 'https://github.com/roskeys/imsi-catcher' note: >- A small research project that modifies srsRAN_4G's srsENB into an active IMSI - catcher — stands up a fake base station that lures UEs and issues an identity + catcher, stands up a fake base station that lures UEs and issues an identity request to extract the IMSI over the unauthenticated pre-AKA NAS exchange. A concrete worked example of the IMSI-catcher attack on srsRAN. --- -A small research project that modifies srsRAN_4G's srsENB into an active IMSI catcher — stands up a fake base station that lures UEs and issues an identity request to extract the IMSI over the unauthenticated pre-AKA NAS exchange. A concrete worked example of the IMSI-catcher attack on srsRAN. +A small research project that modifies srsRAN_4G's srsENB into an active IMSI catcher, stands up a fake base station that lures UEs and issues an identity request to extract the IMSI over the unauthenticated pre-AKA NAS exchange. A concrete worked example of the IMSI-catcher attack on srsRAN. diff --git a/src/content/tools/imsi-catcher.md b/src/content/tools/imsi-catcher.md index 3fba912..3780b56 100644 --- a/src/content/tools/imsi-catcher.md +++ b/src/content/tools/imsi-catcher.md @@ -9,8 +9,8 @@ repo: 'https://github.com/Oros42/IMSI-catcher' note: >- Python tool that reads the GSMTAP stream produced by gr-gsm and pulls the IMSI / TMSI identities the network pages over the air, printing the cellphones it - sees around you. A PASSIVE IMSI catcher — it harvests identities off the + sees around you. A PASSIVE IMSI catcher, it harvests identities off the broadcast/control channels without transmitting anything (no rogue cell); the active catcher is a rogue BTS (osmo-bts / OpenBTS). --- -Python tool that reads the GSMTAP stream produced by gr-gsm and pulls the IMSI / TMSI identities the network pages over the air, printing the cellphones it sees around you. A PASSIVE IMSI catcher — it harvests identities off the broadcast/control channels without transmitting anything (no rogue cell); the active catcher is a rogue BTS (osmo-bts / OpenBTS). +Python tool that reads the GSMTAP stream produced by gr-gsm and pulls the IMSI / TMSI identities the network pages over the air, printing the cellphones it sees around you. A PASSIVE IMSI catcher, it harvests identities off the broadcast/control channels without transmitting anything (no rogue cell); the active catcher is a rogue BTS (osmo-bts / OpenBTS). diff --git a/src/content/tools/killerbee.md b/src/content/tools/killerbee.md index 28224e5..60258c5 100644 --- a/src/content/tools/killerbee.md +++ b/src/content/tools/killerbee.md @@ -10,10 +10,10 @@ repo: 'https://github.com/riverloopsec/killerbee' software: [] note: >- The reference IEEE 802.15.4 / Zigbee security toolkit. A Python framework plus - command tools — zbstumbler (active network discovery), zbid (list capture + command tools, zbstumbler (active network discovery), zbid (list capture interfaces), zbdump (capture to PCAP), zbwireshark (live feed to Wireshark), zbreplay (replay frames) and zbdsniff (extract a network key from a join capture). Drives a range of capture radios (ApiMote, CC2531, nRF52840, RZUSBstick). --- -The reference IEEE 802.15.4 / Zigbee security toolkit. A Python framework plus command tools — zbstumbler (active network discovery), zbid (list capture interfaces), zbdump (capture to PCAP), zbwireshark (live feed to Wireshark), zbreplay (replay frames) and zbdsniff (extract a network key from a join capture). Drives a range of capture radios (ApiMote, CC2531, nRF52840, RZUSBstick). +The reference IEEE 802.15.4 / Zigbee security toolkit. A Python framework plus command tools, zbstumbler (active network discovery), zbid (list capture interfaces), zbdump (capture to PCAP), zbwireshark (live feed to Wireshark), zbreplay (replay frames) and zbdsniff (extract a network key from a join capture). Drives a range of capture radios (ApiMote, CC2531, nRF52840, RZUSBstick). diff --git a/src/content/tools/kismet.md b/src/content/tools/kismet.md index 31c2aec..c3049b0 100644 --- a/src/content/tools/kismet.md +++ b/src/content/tools/kismet.md @@ -11,9 +11,9 @@ repo: 'https://github.com/kismetwireless/kismet' note: >- Passive wireless detector, sniffer and wardriving tool. Channel-hops to log every AP, client and SSID (with GPS) and captures to pcapng without ever - transmitting — the reference quiet survey/capture tool. Beyond Wi-Fi it has + transmitting, the reference quiet survey/capture tool. Beyond Wi-Fi it has the widest 802.15.4/Zigbee datasource support of any tool here: a dedicated - CatSniffer v3 Zigbee source (channels 12–26) plus nRF52840, CC2531, + CatSniffer v3 Zigbee source (channels 12 to 26) plus nRF52840, CC2531, RZUSBstick, nRF51822 and NXP KW41Z (Kismet git / 2025-10+ releases). --- -Passive wireless detector, sniffer and wardriving tool. Channel-hops to log every AP, client and SSID (with GPS) and captures to pcapng without ever transmitting — the reference quiet survey/capture tool. Beyond Wi-Fi it has the widest 802.15.4/Zigbee datasource support of any tool here: a dedicated CatSniffer v3 Zigbee source (channels 12–26) plus nRF52840, CC2531, RZUSBstick, nRF51822 and NXP KW41Z (Kismet git / 2025-10+ releases). +Passive wireless detector, sniffer and wardriving tool. Channel-hops to log every AP, client and SSID (with GPS) and captures to pcapng without ever transmitting, the reference quiet survey/capture tool. Beyond Wi-Fi it has the widest 802.15.4/Zigbee datasource support of any tool here: a dedicated CatSniffer v3 Zigbee source (channels 12 to 26) plus nRF52840, CC2531, RZUSBstick, nRF51822 and NXP KW41Z (Kismet git / 2025-10+ releases). diff --git a/src/content/tools/kraken-a51.md b/src/content/tools/kraken-a51.md index 47766b3..5debe13 100644 --- a/src/content/tools/kraken-a51.md +++ b/src/content/tools/kraken-a51.md @@ -8,9 +8,9 @@ protocols: repo: 'https://github.com/joswr1ght/kraken' note: >- GPU/CPU cracker that recovers an A5/1 session key from a captured keystream - segment using the ~1.6–2 TB A5/1 rainbow tables (the Berlin A5/1 Security + segment using the ~1.6 to 2 TB A5/1 rainbow tables (the Berlin A5/1 Security Project). Recovers Kc, which decrypts the rest of a captured call/SMS session. Old but the reference open A5/1 attack; requires the bulky precomputed tables and a known-keystream slice from the capture. --- -GPU/CPU cracker that recovers an A5/1 session key from a captured keystream segment using the ~1.6–2 TB A5/1 rainbow tables (the Berlin A5/1 Security Project). Recovers Kc, which decrypts the rest of a captured call/SMS session. Old but the reference open A5/1 attack; requires the bulky precomputed tables and a known-keystream slice from the capture. +GPU/CPU cracker that recovers an A5/1 session key from a captured keystream segment using the ~1.6 to 2 TB A5/1 rainbow tables (the Berlin A5/1 Security Project). Recovers Kc, which decrypts the rest of a captured call/SMS session. Old but the reference open A5/1 attack; requires the bulky precomputed tables and a known-keystream slice from the capture. diff --git a/src/content/tools/laf.md b/src/content/tools/laf.md index 1929ae1..1001000 100644 --- a/src/content/tools/laf.md +++ b/src/content/tools/laf.md @@ -8,7 +8,7 @@ protocols: repo: 'https://github.com/IOActive/laf' note: >- Tools to craft, parse, send, analyse and crack LoRaWAN packets to audit or - pentest a LoRaWAN infrastructure — MIC recomputation/validation, key-candidate + pentest a LoRaWAN infrastructure, MIC recomputation/validation, key-candidate testing and frame forging. --- -Tools to craft, parse, send, analyse and crack LoRaWAN packets to audit or pentest a LoRaWAN infrastructure — MIC recomputation/validation, key-candidate testing and frame forging. +Tools to craft, parse, send, analyse and crack LoRaWAN packets to audit or pentest a LoRaWAN infrastructure, MIC recomputation/validation, key-candidate testing and frame forging. diff --git a/src/content/tools/libnfc.md b/src/content/tools/libnfc.md index 4d78ecb..3d0d639 100644 --- a/src/content/tools/libnfc.md +++ b/src/content/tools/libnfc.md @@ -9,7 +9,6 @@ protocols: repo: 'https://github.com/nfc-tools/libnfc' note: >- Platform-independent NFC library and tools (nfc-list, nfc-mfclassic) that - drive PN532/ACR122U-class HF readers to read and dump ISO 14443-A MIFARE cards - — and the host stack the mfoc and mfcuk Crypto1 crackers build on. + drive PN532/ACR122U-class HF readers to read and dump ISO 14443-A MIFARE cards, and the host stack the mfoc and mfcuk Crypto1 crackers build on. --- -Platform-independent NFC library and tools (nfc-list, nfc-mfclassic) that drive PN532/ACR122U-class HF readers to read and dump ISO 14443-A MIFARE cards — and the host stack the mfoc and mfcuk Crypto1 crackers build on. +Platform-independent NFC library and tools (nfc-list, nfc-mfclassic) that drive PN532/ACR122U-class HF readers to read and dump ISO 14443-A MIFARE cards, and the host stack the mfoc and mfcuk Crypto1 crackers build on. diff --git a/src/content/tools/lora-wideband-decoder.md b/src/content/tools/lora-wideband-decoder.md index 3a2ec18..2573a20 100644 --- a/src/content/tools/lora-wideband-decoder.md +++ b/src/content/tools/lora-wideband-decoder.md @@ -14,7 +14,7 @@ note: >- SF7-SF12 at every standard bandwidth (62.5/125/250/500 kHz) in software, near-real-time, surfacing decoded packets, node identities and a live spectrum waterfall in a local Flask web UI. Captures the whole sub-band at once (~28 - Msps on a multi-core host) rather than one channel — validated on bladeRF + Msps on a multi-core host) rather than one channel, validated on bladeRF (native, 28 Msps) and USRP B210/B205mini (SoapyUHD). --- -Self-hosted wideband LoRa intercept receiver: streams wideband IQ from a SoapySDR/bladeRF SDR and decodes Meshtastic, LoRaWAN and MeshCore across SF7-SF12 at every standard bandwidth (62.5/125/250/500 kHz) in software, near-real-time, surfacing decoded packets, node identities and a live spectrum waterfall in a local Flask web UI. Captures the whole sub-band at once (~28 Msps on a multi-core host) rather than one channel — validated on bladeRF (native, 28 Msps) and USRP B210/B205mini (SoapyUHD). +Self-hosted wideband LoRa intercept receiver: streams wideband IQ from a SoapySDR/bladeRF SDR and decodes Meshtastic, LoRaWAN and MeshCore across SF7-SF12 at every standard bandwidth (62.5/125/250/500 kHz) in software, near-real-time, surfacing decoded packets, node identities and a live spectrum waterfall in a local Flask web UI. Captures the whole sub-band at once (~28 Msps on a multi-core host) rather than one channel, validated on bladeRF (native, 28 Msps) and USRP B210/B205mini (SoapyUHD). diff --git a/src/content/tools/m5-cardputer.md b/src/content/tools/m5-cardputer.md index 2ec3e63..16b69a1 100644 --- a/src/content/tools/m5-cardputer.md +++ b/src/content/tools/m5-cardputer.md @@ -15,7 +15,7 @@ software: note: >- Pocket keyboard-computer on the M5StampS3 (ESP32-S3): full keyboard, LCD, microSD, IR and battery in a card-sized case. A pentest-community favourite - chassis — runs ESP32 Marauder, Bruce and Ghost ESP out of the box (Marauder + chassis, runs ESP32 Marauder, Bruce and Ghost ESP out of the box (Marauder added Cardputer ADV support in v1.12.0). Bruce's flagship target. --- -Pocket keyboard-computer on the M5StampS3 (ESP32-S3): full keyboard, LCD, microSD, IR and battery in a card-sized case. A pentest-community favourite chassis — runs ESP32 Marauder, Bruce and Ghost ESP out of the box (Marauder added Cardputer ADV support in v1.12.0). Bruce's flagship target. +Pocket keyboard-computer on the M5StampS3 (ESP32-S3): full keyboard, LCD, microSD, IR and battery in a card-sized case. A pentest-community favourite chassis, runs ESP32 Marauder, Bruce and Ghost ESP out of the box (Marauder added Cardputer ADV support in v1.12.0). Bruce's flagship target. diff --git a/src/content/tools/makerfabs-esp32-uwb-dw3000.md b/src/content/tools/makerfabs-esp32-uwb-dw3000.md index 4810ca5..51a77fe 100644 --- a/src/content/tools/makerfabs-esp32-uwb-dw3000.md +++ b/src/content/tools/makerfabs-esp32-uwb-dw3000.md @@ -13,11 +13,11 @@ software: - dwm3000-dwt-driver note: >- Low-cost open hobbyist board pairing an ESP32 with a Qorvo DW3000 (DW3110) UWB - transceiver — the accessible way to bring up two-way ranging and tag/anchor + transceiver, the accessible way to bring up two-way ranging and tag/anchor positioning experiments in the Arduino/ESP-IDF ecosystem. Open example firmware and an Arduino DW3000 library ship in the Makerfabs GitHub repo. A development/ranging board, not a turnkey sniffer; use it to learn the radio, characterise a scheme's parameters, or build a controllable peer for authorised testing. --- -Low-cost open hobbyist board pairing an ESP32 with a Qorvo DW3000 (DW3110) UWB transceiver — the accessible way to bring up two-way ranging and tag/anchor positioning experiments in the Arduino/ESP-IDF ecosystem. Open example firmware and an Arduino DW3000 library ship in the Makerfabs GitHub repo. A development/ranging board, not a turnkey sniffer; use it to learn the radio, characterise a scheme's parameters, or build a controllable peer for authorised testing. +Low-cost open hobbyist board pairing an ESP32 with a Qorvo DW3000 (DW3110) UWB transceiver, the accessible way to bring up two-way ranging and tag/anchor positioning experiments in the Arduino/ESP-IDF ecosystem. Open example firmware and an Arduino DW3000 library ship in the Makerfabs GitHub repo. A development/ranging board, not a turnkey sniffer; use it to learn the radio, characterise a scheme's parameters, or build a controllable peer for authorised testing. diff --git a/src/content/tools/marauder-ui-android-app.md b/src/content/tools/marauder-ui-android-app.md index 10e8621..f458ae2 100644 --- a/src/content/tools/marauder-ui-android-app.md +++ b/src/content/tools/marauder-ui-android-app.md @@ -11,7 +11,7 @@ repo: 'https://github.com/ElectronicCats/marauder-ui-android-app' note: >- Electronic Cats' Android companion app that drives an ESP32 Marauder board over a phone UI instead of the on-device screen. A host front-end for the - Marauder firmware (not a firmware or a board itself) — the EC tie-in to the + Marauder firmware (not a firmware or a board itself), the EC tie-in to the ESP32 Marauder ecosystem. --- -Electronic Cats' Android companion app that drives an ESP32 Marauder board over a phone UI instead of the on-device screen. A host front-end for the Marauder firmware (not a firmware or a board itself) — the EC tie-in to the ESP32 Marauder ecosystem. +Electronic Cats' Android companion app that drives an ESP32 Marauder board over a phone UI instead of the on-device screen. A host front-end for the Marauder firmware (not a firmware or a board itself), the EC tie-in to the ESP32 Marauder ecosystem. diff --git a/src/content/tools/matter-dcl.md b/src/content/tools/matter-dcl.md index edc0e14..78c6c74 100644 --- a/src/content/tools/matter-dcl.md +++ b/src/content/tools/matter-dcl.md @@ -15,7 +15,7 @@ note: >- certification status, and the Product Attestation Authority (PAA) root certificates that commissioners trust for device attestation. At Identify, the DCL turns the VID/PID read off a device's onboarding payload into a known - vendor/product and certification record — and a Test-Vendor VID - (0xFFF1–0xFFF4) on a 'production' device is an immediate red flag. + vendor/product and certification record, and a Test-Vendor VID + (0xFFF1 to 0xFFF4) on a 'production' device is an immediate red flag. --- -The CSA-run public ledger (Cosmos SDK / CometBFT) of Matter device data: vendor and product info keyed by Vendor ID (VID) and Product ID (PID), certification status, and the Product Attestation Authority (PAA) root certificates that commissioners trust for device attestation. At Identify, the DCL turns the VID/PID read off a device's onboarding payload into a known vendor/product and certification record — and a Test-Vendor VID (0xFFF1–0xFFF4) on a 'production' device is an immediate red flag. +The CSA-run public ledger (Cosmos SDK / CometBFT) of Matter device data: vendor and product info keyed by Vendor ID (VID) and Product ID (PID), certification status, and the Product Attestation Authority (PAA) root certificates that commissioners trust for device attestation. At Identify, the DCL turns the VID/PID read off a device's onboarding payload into a known vendor/product and certification record, and a Test-Vendor VID (0xFFF1 to 0xFFF4) on a 'production' device is an immediate red flag. diff --git a/src/content/tools/mdek1001.md b/src/content/tools/mdek1001.md index 31b7151..606510f 100644 --- a/src/content/tools/mdek1001.md +++ b/src/content/tools/mdek1001.md @@ -13,10 +13,10 @@ note: >- The classic first-generation Decawave/Qorvo RTLS development kit: twelve enclosed DWM1001-DEV boards (each a DW1000 UWB transceiver plus an nRF52832 host), configurable as anchors, tags or bridge nodes to stand up a real-time - location system out of the box. DW1000 is the older generation — it predates - the 802.15.4z STS security enhancements that the DW3000 family adds — so it is + location system out of the box. DW1000 is the older generation, it predates + the 802.15.4z STS security enhancements that the DW3000 family adds, so it is ideal for learning UWB ranging mechanics, less so for assessing modern secure-ranging schemes. Note: end-of-life as of Dec 2025 (last orders mid-2026); Qorvo points new designs at the QM33-series kits. --- -The classic first-generation Decawave/Qorvo RTLS development kit: twelve enclosed DWM1001-DEV boards (each a DW1000 UWB transceiver plus an nRF52832 host), configurable as anchors, tags or bridge nodes to stand up a real-time location system out of the box. DW1000 is the older generation — it predates the 802.15.4z STS security enhancements that the DW3000 family adds — so it is ideal for learning UWB ranging mechanics, less so for assessing modern secure-ranging schemes. Note: end-of-life as of Dec 2025 (last orders mid-2026); Qorvo points new designs at the QM33-series kits. +The classic first-generation Decawave/Qorvo RTLS development kit: twelve enclosed DWM1001-DEV boards (each a DW1000 UWB transceiver plus an nRF52832 host), configurable as anchors, tags or bridge nodes to stand up a real-time location system out of the box. DW1000 is the older generation, it predates the 802.15.4z STS security enhancements that the DW3000 family adds, so it is ideal for learning UWB ranging mechanics, less so for assessing modern secure-ranging schemes. Note: end-of-life as of Dec 2025 (last orders mid-2026); Qorvo points new designs at the QM33-series kits. diff --git a/src/content/tools/mdk4.md b/src/content/tools/mdk4.md index a725598..79102b7 100644 --- a/src/content/tools/mdk4.md +++ b/src/content/tools/mdk4.md @@ -8,7 +8,7 @@ protocols: repo: 'https://github.com/aircrack-ng/mdk4' note: >- 802.11 stress-testing and DoS toolkit: deauthentication floods, beacon floods - (fake SSIDs), authentication floods, probe and other attacks — for testing how + (fake SSIDs), authentication floods, probe and other attacks, for testing how an AP and clients hold up under adversarial traffic. --- -802.11 stress-testing and DoS toolkit: deauthentication floods, beacon floods (fake SSIDs), authentication floods, probe and other attacks — for testing how an AP and clients hold up under adversarial traffic. +802.11 stress-testing and DoS toolkit: deauthentication floods, beacon floods (fake SSIDs), authentication floods, probe and other attacks, for testing how an AP and clients hold up under adversarial traffic. diff --git a/src/content/tools/mfcuk.md b/src/content/tools/mfcuk.md index fc0c129..08bb6a4 100644 --- a/src/content/tools/mfcuk.md +++ b/src/content/tools/mfcuk.md @@ -9,7 +9,7 @@ protocols: repo: 'https://github.com/nfc-tools/mfcuk' note: >- MiFare Classic Universal toolKit implementing the darkside attack to recover a - first Crypto1 key when no default key works — the bootstrap that lets mfoc + first Crypto1 key when no default key works, the bootstrap that lets mfoc finish the rest. Runs on a libnfc PN532/ACR122U reader. --- -MiFare Classic Universal toolKit implementing the darkside attack to recover a first Crypto1 key when no default key works — the bootstrap that lets mfoc finish the rest. Runs on a libnfc PN532/ACR122U reader. +MiFare Classic Universal toolKit implementing the darkside attack to recover a first Crypto1 key when no default key works, the bootstrap that lets mfoc finish the rest. Runs on a libnfc PN532/ACR122U reader. diff --git a/src/content/tools/mfdread.md b/src/content/tools/mfdread.md index e87cd01..36749f3 100644 --- a/src/content/tools/mfdread.md +++ b/src/content/tools/mfdread.md @@ -8,8 +8,8 @@ protocols: - RFID repo: 'https://github.com/zhovner/mfdread' note: >- - Parses MIFARE Classic 1k/4k dumps into human-readable form — per-sector data, - keys A/B and access-condition bits — so a recovered dump becomes readable + Parses MIFARE Classic 1k/4k dumps into human-readable form, per-sector data, + keys A/B and access-condition bits, so a recovered dump becomes readable application data. --- -Parses MIFARE Classic 1k/4k dumps into human-readable form — per-sector data, keys A/B and access-condition bits — so a recovered dump becomes readable application data. +Parses MIFARE Classic 1k/4k dumps into human-readable form, per-sector data, keys A/B and access-condition bits, so a recovered dump becomes readable application data. diff --git a/src/content/tools/minino.md b/src/content/tools/minino.md index 2a72054..3b4be29 100644 --- a/src/content/tools/minino.md +++ b/src/content/tools/minino.md @@ -14,8 +14,8 @@ note: >- ESP32-C6 pocket multitool (GPS, microSD, OLED). For Wi-Fi (2.4 GHz only) it does wardriving, an AP/SSID sniffer with Wireshark-compatible output, a deauther and console-driven DoS, an analyzer, SSID spammer, and Wi-Fi - deauthentication detection. It also has a native BLE suite — an advertising - scanner, tracker/AirTag detection, BLE notification spam and BLE HID — plus + deauthentication detection. It also has a native BLE suite, an advertising + scanner, tracker/AirTag detection, BLE notification spam and BLE HID, plus 802.15.4 (Zigbee/Thread) field recon. --- -ESP32-C6 pocket multitool (GPS, microSD, OLED). For Wi-Fi (2.4 GHz only) it does wardriving, an AP/SSID sniffer with Wireshark-compatible output, a deauther and console-driven DoS, an analyzer, SSID spammer, and Wi-Fi deauthentication detection. It also has a native BLE suite — an advertising scanner, tracker/AirTag detection, BLE notification spam and BLE HID — plus 802.15.4 (Zigbee/Thread) field recon. +ESP32-C6 pocket multitool (GPS, microSD, OLED). For Wi-Fi (2.4 GHz only) it does wardriving, an AP/SSID sniffer with Wireshark-compatible output, a deauther and console-driven DoS, an analyzer, SSID spammer, and Wi-Fi deauthentication detection. It also has a native BLE suite, an advertising scanner, tracker/AirTag detection, BLE notification spam and BLE HID, plus 802.15.4 (Zigbee/Thread) field recon. diff --git a/src/content/tools/murata-type2bp.md b/src/content/tools/murata-type2bp.md index 9602075..53268e7 100644 --- a/src/content/tools/murata-type2bp.md +++ b/src/content/tools/murata-type2bp.md @@ -7,15 +7,14 @@ protocols: - UWB homepage: 'https://www.murata.com/products/connectivitymodule/ultra-wide-band/nxp/type2bp' spec: >- - NXP Trimension SR150 chipset · FiRa Certified · UWB ch 5 / ch 9 (6.25–8.25 + NXP Trimension SR150 chipset · FiRa Certified · UWB ch 5 / ch 9 (6.25 to 8.25 GHz) · two-way ranging + 2D/3D Angle-of-Arrival (up to 3 antennas) · SPI note: >- - A compact production UWB module built on NXP's Trimension SR150 (not a DW3000) - — included here because the NXP UWB silicon family is the other half of the + A compact production UWB module built on NXP's Trimension SR150 (not a DW3000), included here because the NXP UWB silicon family is the other half of the deployed ecosystem (NXP chips feature in car digital-key and phone designs, and inter-operate with Apple U1 in the Ghost Peak results). FiRa Certified, supports two-way ranging and 2D/3D Angle-of-Arrival with up to three antennas. A module for building/representing an NXP-based ranging peer; identify it by its SR150 silicon rather than assuming every UWB target is a Qorvo DW3000. --- -A compact production UWB module built on NXP's Trimension SR150 (not a DW3000) — included here because the NXP UWB silicon family is the other half of the deployed ecosystem (NXP chips feature in car digital-key and phone designs, and inter-operate with Apple U1 in the Ghost Peak results). FiRa Certified, supports two-way ranging and 2D/3D Angle-of-Arrival with up to three antennas. A module for building/representing an NXP-based ranging peer; identify it by its SR150 silicon rather than assuming every UWB target is a Qorvo DW3000. +A compact production UWB module built on NXP's Trimension SR150 (not a DW3000), included here because the NXP UWB silicon family is the other half of the deployed ecosystem (NXP chips feature in car digital-key and phone designs, and inter-operate with Apple U1 in the Ghost Peak results). FiRa Certified, supports two-way ranging and 2D/3D Angle-of-Arrival with up to three antennas. A module for building/representing an NXP-based ranging peer; identify it by its SR150 silicon rather than assuming every UWB target is a Qorvo DW3000. diff --git a/src/content/tools/openairinterface5g.md b/src/content/tools/openairinterface5g.md index ca3716e..94279aa 100644 --- a/src/content/tools/openairinterface5g.md +++ b/src/content/tools/openairinterface5g.md @@ -9,8 +9,8 @@ repo: 'https://github.com/openairinterface/openairinterface5g' homepage: 'https://openairinterface.org' note: >- Full open-source LTE/NR RAN and core reference stack (eNodeB/gNB, UE and EPC). - A second independent platform — alongside srsRAN — for standing up a + A second independent platform, alongside srsRAN, for standing up a test/rogue eNodeB on a TX-capable SDR and for RRC/NAS signalling experiments and protocol fuzzing in an authorised lab. --- -Full open-source LTE/NR RAN and core reference stack (eNodeB/gNB, UE and EPC). A second independent platform — alongside srsRAN — for standing up a test/rogue eNodeB on a TX-capable SDR and for RRC/NAS signalling experiments and protocol fuzzing in an authorised lab. +Full open-source LTE/NR RAN and core reference stack (eNodeB/gNB, UE and EPC). A second independent platform, alongside srsRAN, for standing up a test/rogue eNodeB on a TX-capable SDR and for RRC/NAS signalling experiments and protocol fuzzing in an authorised lab. diff --git a/src/content/tools/openhaystack.md b/src/content/tools/openhaystack.md index 2cfb538..daac895 100644 --- a/src/content/tools/openhaystack.md +++ b/src/content/tools/openhaystack.md @@ -9,9 +9,9 @@ repo: 'https://github.com/seemoo-lab/openhaystack' note: >- Academic framework for tracking personal BLE devices via Apple's Find My network (~13k stars, AGPL-3.0). It ships ESP32 (and nRF51822) firmware that - advertises as a Find My beacon, so an ESP32 can act as a DIY 'AirTag' — the + advertises as a Find My beacon, so an ESP32 can act as a DIY 'AirTag', the AirTag/Find-My beacon spoof/emulation path on cheap hardware. Authorised research only; covertly placing a Find My beacon to track a person is unlawful. --- -Academic framework for tracking personal BLE devices via Apple's Find My network (~13k stars, AGPL-3.0). It ships ESP32 (and nRF51822) firmware that advertises as a Find My beacon, so an ESP32 can act as a DIY 'AirTag' — the AirTag/Find-My beacon spoof/emulation path on cheap hardware. Authorised research only; covertly placing a Find My beacon to track a person is unlawful. +Academic framework for tracking personal BLE devices via Apple's Find My network (~13k stars, AGPL-3.0). It ships ESP32 (and nRF51822) firmware that advertises as a Find My beacon, so an ESP32 can act as a DIY 'AirTag', the AirTag/Find-My beacon spoof/emulation path on cheap hardware. Authorised research only; covertly placing a Find My beacon to track a person is unlawful. diff --git a/src/content/tools/orbic-rc400l.md b/src/content/tools/orbic-rc400l.md index 726a5a9..0d0bc2d 100644 --- a/src/content/tools/orbic-rc400l.md +++ b/src/content/tools/orbic-rc400l.md @@ -8,10 +8,10 @@ protocols: spec: LTE Cat-4 mobile hotspot · Qualcomm modem (/dev/diag) homepage: 'https://efforg.github.io/rayhunter/supported-devices.html' note: >- - Low-cost (~US$20–30) Qualcomm-based LTE mobile hotspot (also branded Kajeet - RC400L) that exposes a /dev/diag diagnostic interface — the reference, + Low-cost (~US$20 to 30) Qualcomm-based LTE mobile hotspot (also branded Kajeet + RC400L) that exposes a /dev/diag diagnostic interface, the reference, best-tested hardware for running EFF's Rayhunter IMSI-catcher detector. The TP-Link M7350 is also supported; in principle any device with a Qualcomm modem exposing /dev/diag may work. --- -Low-cost (~US$20–30) Qualcomm-based LTE mobile hotspot (also branded Kajeet RC400L) that exposes a /dev/diag diagnostic interface — the reference, best-tested hardware for running EFF's Rayhunter IMSI-catcher detector. The TP-Link M7350 is also supported; in principle any device with a Qualcomm modem exposing /dev/diag may work. +Low-cost (~US$20 to 30) Qualcomm-based LTE mobile hotspot (also branded Kajeet RC400L) that exposes a /dev/diag diagnostic interface, the reference, best-tested hardware for running EFF's Rayhunter IMSI-catcher detector. The TP-Link M7350 is also supported; in principle any device with a Qualcomm modem exposing /dev/diag may work. diff --git a/src/content/tools/osmo-bts.md b/src/content/tools/osmo-bts.md index c1c0170..7e0ea1b 100644 --- a/src/content/tools/osmo-bts.md +++ b/src/content/tools/osmo-bts.md @@ -10,7 +10,7 @@ repo: 'https://github.com/osmocom/osmo-bts' note: >- The Osmocom open GSM network stack: osmo-trx drives the SDR, osmo-bts is the base station, with osmo-bsc / osmo-msc / osmo-hlr forming the core. Together - they stand up a full 2G cell on an SDR — the reference open platform for a + they stand up a full 2G cell on an SDR, the reference open platform for a test/rogue BTS and active IMSI-catcher research. Actively maintained. --- -The Osmocom open GSM network stack: osmo-trx drives the SDR, osmo-bts is the base station, with osmo-bsc / osmo-msc / osmo-hlr forming the core. Together they stand up a full 2G cell on an SDR — the reference open platform for a test/rogue BTS and active IMSI-catcher research. Actively maintained. +The Osmocom open GSM network stack: osmo-trx drives the SDR, osmo-bts is the base station, with osmo-bsc / osmo-msc / osmo-hlr forming the core. Together they stand up a full 2G cell on an SDR, the reference open platform for a test/rogue BTS and active IMSI-catcher research. Actively maintained. diff --git a/src/content/tools/pm3-client.md b/src/content/tools/pm3-client.md index 55da606..f265af7 100644 --- a/src/content/tools/pm3-client.md +++ b/src/content/tools/pm3-client.md @@ -8,7 +8,7 @@ protocols: - RFID repo: 'https://github.com/RfidResearchGroup/proxmark3' note: >- - The host client that drives the Proxmark3 over USB — the `pm3` shell from the + The host client that drives the Proxmark3 over USB, the `pm3` shell from the RfidResearchGroup/proxmark3 (Iceman) repo. Runs every Proxmark workflow from the laptop: `lf/hf search` to fingerprint a tag, read/dump LF IDs and HF cards, the full Crypto1 suite (`hf mf @@ -17,4 +17,4 @@ note: >- firmware and client ship together; this is the software you actually type into. --- -The host client that drives the Proxmark3 over USB — the `pm3` shell from the RfidResearchGroup/proxmark3 (Iceman) repo. Runs every Proxmark workflow from the laptop: `lf/hf search` to fingerprint a tag, read/dump LF IDs and HF cards, the full Crypto1 suite (`hf mf darkside`/`nested`/`hardnested`/`mfkey`), clone/simulate, and `hf 14a` sniff plus the `hf_reblay` standalone mode for an ISO 14443-A relay/MITM. The firmware and client ship together; this is the software you actually type into. +The host client that drives the Proxmark3 over USB, the `pm3` shell from the RfidResearchGroup/proxmark3 (Iceman) repo. Runs every Proxmark workflow from the laptop: `lf/hf search` to fingerprint a tag, read/dump LF IDs and HF cards, the full Crypto1 suite (`hf mf darkside`/`nested`/`hardnested`/`mfkey`), clone/simulate, and `hf 14a` sniff plus the `hf_reblay` standalone mode for an ISO 14443-A relay/MITM. The firmware and client ship together; this is the software you actually type into. diff --git a/src/content/tools/pymodes.md b/src/content/tools/pymodes.md index 4bd0100..b0394de 100644 --- a/src/content/tools/pymodes.md +++ b/src/content/tools/pymodes.md @@ -9,9 +9,9 @@ repo: 'https://github.com/junzis/pyModeS' note: >- A pure-Python decoder library for Mode S and ADS-B messages: feed it hex frames (or stream them from dump1090 over TCP/Beast) and it returns the - decoded fields — ICAO address, callsign, airborne/surface position (CPR), - velocity, altitude — plus DF4/5/11/20/21 surveillance and Comm-B BDS + decoded fields, ICAO address, callsign, airborne/surface position (CPR), + velocity, altitude, plus DF4/5/11/20/21 surveillance and Comm-B BDS registers. The reference way to interpret message contents and to run plausibility / anti-spoof checks on a decoded feed in your own code. --- -A pure-Python decoder library for Mode S and ADS-B messages: feed it hex frames (or stream them from dump1090 over TCP/Beast) and it returns the decoded fields — ICAO address, callsign, airborne/surface position (CPR), velocity, altitude — plus DF4/5/11/20/21 surveillance and Comm-B BDS registers. The reference way to interpret message contents and to run plausibility / anti-spoof checks on a decoded feed in your own code. +A pure-Python decoder library for Mode S and ADS-B messages: feed it hex frames (or stream them from dump1090 over TCP/Beast) and it returns the decoded fields, ICAO address, callsign, airborne/surface position (CPR), velocity, altitude, plus DF4/5/11/20/21 surveillance and Comm-B BDS registers. The reference way to interpret message contents and to run plausibility / anti-spoof checks on a decoded feed in your own code. diff --git a/src/content/tools/python-matter-server.md b/src/content/tools/python-matter-server.md index 527139a..4bcd372 100644 --- a/src/content/tools/python-matter-server.md +++ b/src/content/tools/python-matter-server.md @@ -12,8 +12,8 @@ note: >- A CSA-certified Matter Controller Server (the one behind Home Assistant's Matter integration) that wraps the CHIP SDK and exposes commissioning and the operational cluster model over a WebSocket API. Acts as a standing - controller/commissioner you can drive programmatically — commission a node + controller/commissioner you can drive programmatically, commission a node over BLE, then enumerate and exercise its clusters. Maintenance mode (being rebuilt on matter.js), but a real, working Matter controller. --- -A CSA-certified Matter Controller Server (the one behind Home Assistant's Matter integration) that wraps the CHIP SDK and exposes commissioning and the operational cluster model over a WebSocket API. Acts as a standing controller/commissioner you can drive programmatically — commission a node over BLE, then enumerate and exercise its clusters. Maintenance mode (being rebuilt on matter.js), but a real, working Matter controller. +A CSA-certified Matter Controller Server (the one behind Home Assistant's Matter integration) that wraps the CHIP SDK and exposes commissioning and the operational cluster model over a WebSocket API. Acts as a standing controller/commissioner you can drive programmatically, commission a node over BLE, then enumerate and exercise its clusters. Maintenance mode (being rebuilt on matter.js), but a real, working Matter controller. diff --git a/src/content/tools/qcsuper.md b/src/content/tools/qcsuper.md index 6ea04ec..cc6174e 100644 --- a/src/content/tools/qcsuper.md +++ b/src/content/tools/qcsuper.md @@ -11,7 +11,7 @@ note: >- Captures raw 2G/3G/4G (and, on some modems, 5G) radio frames from Qualcomm-based phones and modems via the /dev/diag DIAG interface, wraps them in GSMTAP and streams a live PCAP into Wireshark. Turns a cheap Qualcomm modem - such as the SIM7600 into a passive cellular-signalling sniffer — an + such as the SIM7600 into a passive cellular-signalling sniffer, an alternative to an SDR cell-search receiver. --- -Captures raw 2G/3G/4G (and, on some modems, 5G) radio frames from Qualcomm-based phones and modems via the /dev/diag DIAG interface, wraps them in GSMTAP and streams a live PCAP into Wireshark. Turns a cheap Qualcomm modem such as the SIM7600 into a passive cellular-signalling sniffer — an alternative to an SDR cell-search receiver. +Captures raw 2G/3G/4G (and, on some modems, 5G) radio frames from Qualcomm-based phones and modems via the /dev/diag DIAG interface, wraps them in GSMTAP and streams a live PCAP into Wireshark. Turns a cheap Qualcomm modem such as the SIM7600 into a passive cellular-signalling sniffer, an alternative to an SDR cell-search receiver. diff --git a/src/content/tools/quectel-rm500q.md b/src/content/tools/quectel-rm500q.md index 6d1a029..be48a3a 100644 --- a/src/content/tools/quectel-rm500q.md +++ b/src/content/tools/quectel-rm500q.md @@ -12,7 +12,7 @@ software: note: >- Commercial 5G NR Sub-6 (FR1) modem module built on the Qualcomm Snapdragon X55 (SDX55). Being Qualcomm-based it exposes a DIAG interface, so QCSuper can pull - raw 5G/LTE signalling off it into Wireshark — a no-SDR route to 5G + raw 5G/LTE signalling off it into Wireshark, a no-SDR route to 5G control-plane frames (5G frame coverage is modem/firmware-dependent). --- -Commercial 5G NR Sub-6 (FR1) modem module built on the Qualcomm Snapdragon X55 (SDX55). Being Qualcomm-based it exposes a DIAG interface, so QCSuper can pull raw 5G/LTE signalling off it into Wireshark — a no-SDR route to 5G control-plane frames (5G frame coverage is modem/firmware-dependent). +Commercial 5G NR Sub-6 (FR1) modem module built on the Qualcomm Snapdragon X55 (SDX55). Being Qualcomm-based it exposes a DIAG interface, so QCSuper can pull raw 5G/LTE signalling off it into Wireshark, a no-SDR route to 5G control-plane frames (5G frame coverage is modem/firmware-dependent). diff --git a/src/content/tools/rak-wisgate-connect.md b/src/content/tools/rak-wisgate-connect.md index 1ff562e..3bfd4a5 100644 --- a/src/content/tools/rak-wisgate-connect.md +++ b/src/content/tools/rak-wisgate-connect.md @@ -13,7 +13,7 @@ software: note: >- RAKwireless multi-channel LoRaWAN gateway built on a Raspberry Pi CM4 with an SX1302/SX1303 concentrator. Receives every LoRaWAN channel at once and feeds - frames over the Semtech UDP packet forwarder — the gateway ChirpCat is + frames over the Semtech UDP packet forwarder, the gateway ChirpCat is designed to run on for uplink/downlink capture. --- -RAKwireless multi-channel LoRaWAN gateway built on a Raspberry Pi CM4 with an SX1302/SX1303 concentrator. Receives every LoRaWAN channel at once and feeds frames over the Semtech UDP packet forwarder — the gateway ChirpCat is designed to run on for uplink/downlink capture. +RAKwireless multi-channel LoRaWAN gateway built on a Raspberry Pi CM4 with an SX1302/SX1303 concentrator. Receives every LoRaWAN channel at once and feeds frames over the Semtech UDP packet forwarder, the gateway ChirpCat is designed to run on for uplink/downlink capture. diff --git a/src/content/tools/rayhunter.md b/src/content/tools/rayhunter.md index 0a79487..3b2728a 100644 --- a/src/content/tools/rayhunter.md +++ b/src/content/tools/rayhunter.md @@ -11,9 +11,9 @@ note: >- EFF's IMSI-catcher / cell-site-simulator detector. Runs as firmware on a cheap Qualcomm-based mobile hotspot (Orbic RC400L, TP-Link M7350) and passively analyses the LTE control plane from the modem's /dev/diag feed, raising an - alert on cell-site-simulator behaviour — unexpected identity/IMSI requests, + alert on cell-site-simulator behaviour, unexpected identity/IMSI requests, downgrade attempts or suspicious tower configuration. The portable, low-cost blue-team counterpart to Crocodile Hunter for confirming whether a rogue station is present, with no SDR or host PC. --- -EFF's IMSI-catcher / cell-site-simulator detector. Runs as firmware on a cheap Qualcomm-based mobile hotspot (Orbic RC400L, TP-Link M7350) and passively analyses the LTE control plane from the modem's /dev/diag feed, raising an alert on cell-site-simulator behaviour — unexpected identity/IMSI requests, downgrade attempts or suspicious tower configuration. The portable, low-cost blue-team counterpart to Crocodile Hunter for confirming whether a rogue station is present, with no SDR or host PC. +EFF's IMSI-catcher / cell-site-simulator detector. Runs as firmware on a cheap Qualcomm-based mobile hotspot (Orbic RC400L, TP-Link M7350) and passively analyses the LTE control plane from the modem's /dev/diag feed, raising an alert on cell-site-simulator behaviour, unexpected identity/IMSI requests, downgrade attempts or suspicious tower configuration. The portable, low-cost blue-team counterpart to Crocodile Hunter for confirming whether a rogue station is present, with no SDR or host PC. diff --git a/src/content/tools/rtl-433.md b/src/content/tools/rtl-433.md index 55e9796..cf28fc5 100644 --- a/src/content/tools/rtl-433.md +++ b/src/content/tools/rtl-433.md @@ -8,12 +8,12 @@ protocols: repo: 'https://github.com/merbanan/rtl_433' note: >- Generic ISM-band receiver and decoder for 315 / 433.92 / 868 / 915 MHz - devices. Out of the box it recognises 320+ device protocols — weather and + devices. Out of the box it recognises 320+ device protocols, weather and soil/temperature sensors, TPMS tyre-pressure monitors, energy/water meters, - doorbells, contact sensors and many remotes — and demodulates both OOK/ASK and + doorbells, contact sensors and many remotes, and demodulates both OOK/ASK and FSK, printing each decoded device as a line of JSON (also CSV, MQTT, InfluxDB, syslog). It is itself the decoder: where Wi-Fi or BLE hand a PCAP to Wireshark, rtl_433 turns raw I/Q straight into named, fielded device events. Runs on RTL-SDR natively and on HackRF / other radios via SoapySDR. --- -Generic ISM-band receiver and decoder for 315 / 433.92 / 868 / 915 MHz devices. Out of the box it recognises 320+ device protocols — weather and soil/temperature sensors, TPMS tyre-pressure monitors, energy/water meters, doorbells, contact sensors and many remotes — and demodulates both OOK/ASK and FSK, printing each decoded device as a line of JSON (also CSV, MQTT, InfluxDB, syslog). It is itself the decoder: where Wi-Fi or BLE hand a PCAP to Wireshark, rtl_433 turns raw I/Q straight into named, fielded device events. Runs on RTL-SDR natively and on HackRF / other radios via SoapySDR. +Generic ISM-band receiver and decoder for 315 / 433.92 / 868 / 915 MHz devices. Out of the box it recognises 320+ device protocols, weather and soil/temperature sensors, TPMS tyre-pressure monitors, energy/water meters, doorbells, contact sensors and many remotes, and demodulates both OOK/ASK and FSK, printing each decoded device as a line of JSON (also CSV, MQTT, InfluxDB, syslog). It is itself the decoder: where Wi-Fi or BLE hand a PCAP to Wireshark, rtl_433 turns raw I/Q straight into named, fielded device events. Runs on RTL-SDR natively and on HackRF / other radios via SoapySDR. diff --git a/src/content/tools/rtl-sdr-v4.md b/src/content/tools/rtl-sdr-v4.md index 86a1b2c..5f3f6db 100644 --- a/src/content/tools/rtl-sdr-v4.md +++ b/src/content/tools/rtl-sdr-v4.md @@ -5,11 +5,11 @@ vendor: RTL-SDR Blog type: hardware protocols: - RX-only SDR -spec: ~2.4 MHz BW · 0.5 kHz–1.766 GHz · RX only +spec: ~2.4 MHz BW · 0.5 kHz to 1.766 GHz · RX only homepage: 'https://www.rtl-sdr.com/v4/' note: >- Budget RX-only dongle. Does NOT reach 2.4 GHz, so it cannot receive BLE, Wi-Fi - or Zigbee — but it is a fine cheap receiver for sub-GHz, LoRa and ADS-B (1090 + or Zigbee, but it is a fine cheap receiver for sub-GHz, LoRa and ADS-B (1090 MHz). --- -Budget RX-only dongle. Does NOT reach 2.4 GHz, so it cannot receive BLE, Wi-Fi or Zigbee — but it is a fine cheap receiver for sub-GHz, LoRa and ADS-B (1090 MHz). +Budget RX-only dongle. Does NOT reach 2.4 GHz, so it cannot receive BLE, Wi-Fi or Zigbee, but it is a fine cheap receiver for sub-GHz, LoRa and ADS-B (1090 MHz). diff --git a/src/content/tools/rtl-zwave.md b/src/content/tools/rtl-zwave.md index c38d394..d0867d6 100644 --- a/src/content/tools/rtl-zwave.md +++ b/src/content/tools/rtl-zwave.md @@ -10,7 +10,7 @@ software: [] note: >- The original G.9959 (Z-Wave) demodulator for the RTL-SDR: pipe `rtl_sdr` samples into it and it prints decoded Z-Wave frames. Lightweight, - receive-only, and the codebase Waving-Z grew out of — a minimal way to confirm + receive-only, and the codebase Waving-Z grew out of, a minimal way to confirm Z-Wave traffic and read frame headers on a ~$30 dongle. --- -The original G.9959 (Z-Wave) demodulator for the RTL-SDR: pipe `rtl_sdr` samples into it and it prints decoded Z-Wave frames. Lightweight, receive-only, and the codebase Waving-Z grew out of — a minimal way to confirm Z-Wave traffic and read frame headers on a ~$30 dongle. +The original G.9959 (Z-Wave) demodulator for the RTL-SDR: pipe `rtl_sdr` samples into it and it prints decoded Z-Wave frames. Lightweight, receive-only, and the codebase Waving-Z grew out of, a minimal way to confirm Z-Wave traffic and read frame headers on a ~$30 dongle. diff --git a/src/content/tools/scapy-radio.md b/src/content/tools/scapy-radio.md index a2caada..95165b5 100644 --- a/src/content/tools/scapy-radio.md +++ b/src/content/tools/scapy-radio.md @@ -9,9 +9,9 @@ repo: 'https://github.com/BastilleResearch/scapy-radio' software: [] note: >- GNU Radio flowgraphs plus a patched Scapy that lets you sniff, dissect, craft - and replay several sub-GHz/2.4 GHz protocols — including a Z-Wave layer — + and replay several sub-GHz/2.4 GHz protocols, including a Z-Wave layer, straight from a Python/Scapy session over an SDR (HackRF). The radio/Scapy plumbing EZ-Wave builds on, and a standalone way to script Z-Wave frame capture and injection. --- -GNU Radio flowgraphs plus a patched Scapy that lets you sniff, dissect, craft and replay several sub-GHz/2.4 GHz protocols — including a Z-Wave layer — straight from a Python/Scapy session over an SDR (HackRF). The radio/Scapy plumbing EZ-Wave builds on, and a standalone way to script Z-Wave frame capture and injection. +GNU Radio flowgraphs plus a patched Scapy that lets you sniff, dissect, craft and replay several sub-GHz/2.4 GHz protocols, including a Z-Wave layer, straight from a Python/Scapy session over an SDR (HackRF). The radio/Scapy plumbing EZ-Wave builds on, and a standalone way to script Z-Wave frame capture and injection. diff --git a/src/content/tools/seemoo-uwb-sniffer.md b/src/content/tools/seemoo-uwb-sniffer.md index 65a8412..b9b7401 100644 --- a/src/content/tools/seemoo-uwb-sniffer.md +++ b/src/content/tools/seemoo-uwb-sniffer.md @@ -14,8 +14,8 @@ note: >- out of the SEEMOO/ETH Ghost Peak line of research. Honest limits: UWB has many PHY parameters (channel, preamble code, data rate, STS mode and length) that must be known IN ADVANCE to lock onto a link, and it forwards malformed frames - too — so it is a research instrument, not a push-button capture. It does NOT + too, so it is a research instrument, not a push-button capture. It does NOT break the STS or recover keys; it captures the over-the-air frames you can already decode. --- -The reference OPEN UWB sniffer: firmware for a Qorvo DWM3000EVB driven by a host (a NUCLEO-F429ZI in the reference build; an nRF52840 with code changes) that captures IEEE 802.15.4z UWB frames and forwards them to Wireshark over a sensniff named pipe, with timestamps at the DW3000's 15.65 ps accuracy. Comes out of the SEEMOO/ETH Ghost Peak line of research. Honest limits: UWB has many PHY parameters (channel, preamble code, data rate, STS mode and length) that must be known IN ADVANCE to lock onto a link, and it forwards malformed frames too — so it is a research instrument, not a push-button capture. It does NOT break the STS or recover keys; it captures the over-the-air frames you can already decode. +The reference OPEN UWB sniffer: firmware for a Qorvo DWM3000EVB driven by a host (a NUCLEO-F429ZI in the reference build; an nRF52840 with code changes) that captures IEEE 802.15.4z UWB frames and forwards them to Wireshark over a sensniff named pipe, with timestamps at the DW3000's 15.65 ps accuracy. Comes out of the SEEMOO/ETH Ghost Peak line of research. Honest limits: UWB has many PHY parameters (channel, preamble code, data rate, STS mode and length) that must be known IN ADVANCE to lock onto a link, and it forwards malformed frames too, so it is a research instrument, not a push-button capture. It does NOT break the STS or recover keys; it captures the over-the-air frames you can already decode. diff --git a/src/content/tools/signalsdr-pro.md b/src/content/tools/signalsdr-pro.md index e37955c..b0edc5b 100644 --- a/src/content/tools/signalsdr-pro.md +++ b/src/content/tools/signalsdr-pro.md @@ -5,13 +5,13 @@ vendor: Signalens type: hardware protocols: - Wide-band SDR -spec: 61.44 MHz BW · 70 MHz–6 GHz · 2TX/2RX +spec: 61.44 MHz BW · 70 MHz to 6 GHz · 2TX/2RX homepage: >- https://www.rtl-sdr.com/signalsdr-pro-an-upcoming-sdr-with-70-mhz-to-6-ghz-12-bit-adc-61-44-mhz-bandwidth-and-2tx-2rx-channels/ note: >- AD9361-based SDR in a Raspberry-Pi form factor (Zynq 7020); the widest instantaneous bandwidth in this list at 61.44 MHz, and it can emulate a USRP - B210 / ADALM-Pluto. Newer/emerging product — verify ice9 support and + B210 / ADALM-Pluto. Newer/emerging product, verify ice9 support and availability before relying on it. --- -AD9361-based SDR in a Raspberry-Pi form factor (Zynq 7020); the widest instantaneous bandwidth in this list at 61.44 MHz, and it can emulate a USRP B210 / ADALM-Pluto. Newer/emerging product — verify ice9 support and availability before relying on it. +AD9361-based SDR in a Raspberry-Pi form factor (Zynq 7020); the widest instantaneous bandwidth in this list at 61.44 MHz, and it can emulate a USRP B210 / ADALM-Pluto. Newer/emerging product, verify ice9 support and availability before relying on it. diff --git a/src/content/tools/silabs-uzb7.md b/src/content/tools/silabs-uzb7.md index 2383162..8442522 100644 --- a/src/content/tools/silabs-uzb7.md +++ b/src/content/tools/silabs-uzb7.md @@ -14,9 +14,8 @@ software: - zwave-pc-controller - zwave-zniffer note: >- - Silicon Labs' EFR32ZG14 USB stick that exposes the Z-Wave Serial API to a host - — the controller adapter the Z-Wave PC Controller drives, and (re-flashed with + Silicon Labs' EFR32ZG14 USB stick that exposes the Z-Wave Serial API to a host, the controller adapter the Z-Wave PC Controller drives, and (re-flashed with Zniffer firmware) the capture adapter for the Z-Wave Zniffer. The official native-radio hardware for both vendor tools, ~US$21. --- -Silicon Labs' EFR32ZG14 USB stick that exposes the Z-Wave Serial API to a host — the controller adapter the Z-Wave PC Controller drives, and (re-flashed with Zniffer firmware) the capture adapter for the Z-Wave Zniffer. The official native-radio hardware for both vendor tools, ~US$21. +Silicon Labs' EFR32ZG14 USB stick that exposes the Z-Wave Serial API to a host, the controller adapter the Z-Wave PC Controller drives, and (re-flashed with Zniffer firmware) the capture adapter for the Z-Wave Zniffer. The official native-radio hardware for both vendor tools, ~US$21. diff --git a/src/content/tools/sim7600.md b/src/content/tools/sim7600.md index 5e4289f..2b2f724 100644 --- a/src/content/tools/sim7600.md +++ b/src/content/tools/sim7600.md @@ -9,10 +9,10 @@ spec: LTE Cat-4 modem · multi-band sub-6 GHz homepage: 'https://www.simcom.com' note: >- Low-cost commercial SIMCom LTE Cat-4 modem (Qualcomm MDM-based). Reports - serving- and neighbour-cell information through its own AT command set — + serving- and neighbour-cell information through its own AT command set, AT+CPSI? returns the system mode, operator (MCC-MNC), LAC, Cell ID, band and - EARFCN — a no-SDR way to read which cell a target is on and identify it. + EARFCN, a no-SDR way to read which cell a target is on and identify it. Because the baseband is Qualcomm and exposes a /dev/diag port, the same module can also feed QCSuper to capture raw cellular signalling. --- -Low-cost commercial SIMCom LTE Cat-4 modem (Qualcomm MDM-based). Reports serving- and neighbour-cell information through its own AT command set — AT+CPSI? returns the system mode, operator (MCC-MNC), LAC, Cell ID, band and EARFCN — a no-SDR way to read which cell a target is on and identify it. Because the baseband is Qualcomm and exposes a /dev/diag port, the same module can also feed QCSuper to capture raw cellular signalling. +Low-cost commercial SIMCom LTE Cat-4 modem (Qualcomm MDM-based). Reports serving- and neighbour-cell information through its own AT command set, AT+CPSI? returns the system mode, operator (MCC-MNC), LAC, Cell ID, band and EARFCN, a no-SDR way to read which cell a target is on and identify it. Because the baseband is Qualcomm and exposes a /dev/diag port, the same module can also feed QCSuper to capture raw cellular signalling. diff --git a/src/content/tools/sni5gect.md b/src/content/tools/sni5gect.md index 0cf6625..6311478 100644 --- a/src/content/tools/sni5gect.md +++ b/src/content/tools/sni5gect.md @@ -12,8 +12,8 @@ note: >- Open-source 5G NR sniffer and downlink injector framework built on srsRAN. Passively captures unencrypted MAC-NR messages between a gNB and a UE (with Wireshark support) and can inject crafted MAC-NR packets to a target at - specific post-connection states (registration/authentication/RRC) — used for + specific post-connection states (registration/authentication/RRC), used for modem crashes, downgrades, fingerprinting and auth-bypass research without a rogue base station. Heavy host requirements; FR1 sub-6 GHz on a USRP. --- -Open-source 5G NR sniffer and downlink injector framework built on srsRAN. Passively captures unencrypted MAC-NR messages between a gNB and a UE (with Wireshark support) and can inject crafted MAC-NR packets to a target at specific post-connection states (registration/authentication/RRC) — used for modem crashes, downgrades, fingerprinting and auth-bypass research without a rogue base station. Heavy host requirements; FR1 sub-6 GHz on a USRP. +Open-source 5G NR sniffer and downlink injector framework built on srsRAN. Passively captures unencrypted MAC-NR messages between a gNB and a UE (with Wireshark support) and can inject crafted MAC-NR packets to a target at specific post-connection states (registration/authentication/RRC), used for modem crashes, downgrades, fingerprinting and auth-bypass research without a rogue base station. Heavy host requirements; FR1 sub-6 GHz on a USRP. diff --git a/src/content/tools/sniffle.md b/src/content/tools/sniffle.md index f7f5de7..2abb1e6 100644 --- a/src/content/tools/sniffle.md +++ b/src/content/tools/sniffle.md @@ -9,6 +9,6 @@ repo: 'https://github.com/nccgroup/Sniffle' note: >- The reference modern open-source sniffer for Bluetooth 5 and 4.x LE on TI CC1352/CC26x2 (and CatSniffer). Python host, all BT5 PHYs, extended - advertising, follows connections — the default LL-layer capture choice today. + advertising, follows connections, the default LL-layer capture choice today. --- -The reference modern open-source sniffer for Bluetooth 5 and 4.x LE on TI CC1352/CC26x2 (and CatSniffer). Python host, all BT5 PHYs, extended advertising, follows connections — the default LL-layer capture choice today. +The reference modern open-source sniffer for Bluetooth 5 and 4.x LE on TI CC1352/CC26x2 (and CatSniffer). Python host, all BT5 PHYs, extended advertising, follows connections, the default LL-layer capture choice today. diff --git a/src/content/tools/srsran-4g.md b/src/content/tools/srsran-4g.md index f31b94a..12e930f 100644 --- a/src/content/tools/srsran-4g.md +++ b/src/content/tools/srsran-4g.md @@ -10,7 +10,7 @@ homepage: 'https://www.srsran.com' note: >- Open-source SDR 4G suite: srsUE (cell search, MIB/SIB receiver, MAC-LTE/RRC PCAP output), srsENB (a full eNodeB) and srsEPC. The reference open LTE stack - on HackRF/bladeRF/USRP — passive receiver for Capture, and the basis for + on HackRF/bladeRF/USRP, passive receiver for Capture, and the basis for fake-eNB/IMSI-catcher research when transmitting under authorisation. --- -Open-source SDR 4G suite: srsUE (cell search, MIB/SIB receiver, MAC-LTE/RRC PCAP output), srsENB (a full eNodeB) and srsEPC. The reference open LTE stack on HackRF/bladeRF/USRP — passive receiver for Capture, and the basis for fake-eNB/IMSI-catcher research when transmitting under authorisation. +Open-source SDR 4G suite: srsUE (cell search, MIB/SIB receiver, MAC-LTE/RRC PCAP output), srsENB (a full eNodeB) and srsEPC. The reference open LTE stack on HackRF/bladeRF/USRP, passive receiver for Capture, and the basis for fake-eNB/IMSI-catcher research when transmitting under authorisation. diff --git a/src/content/tools/srsran-project.md b/src/content/tools/srsran-project.md index 51ec46b..6f3c65d 100644 --- a/src/content/tools/srsran-project.md +++ b/src/content/tools/srsran-project.md @@ -10,7 +10,7 @@ homepage: 'https://www.srsran.com' note: >- SRS's O-RAN 5G CU/DU solution (with 4G support). The newer codebase from the srsRAN team; for LTE cell-search/eNodeB work the srsRAN_4G suite is the - directly applicable tool. Note: the srsRAN_Project GitHub repo is archived — + directly applicable tool. Note: the srsRAN_Project GitHub repo is archived, check srsran.com for the current distribution. --- -SRS's O-RAN 5G CU/DU solution (with 4G support). The newer codebase from the srsRAN team; for LTE cell-search/eNodeB work the srsRAN_4G suite is the directly applicable tool. Note: the srsRAN_Project GitHub repo is archived — check srsran.com for the current distribution. +SRS's O-RAN 5G CU/DU solution (with 4G support). The newer codebase from the srsRAN team; for LTE cell-search/eNodeB work the srsRAN_4G suite is the directly applicable tool. Note: the srsRAN_Project GitHub repo is archived, check srsran.com for the current distribution. diff --git a/src/content/tools/stm32wlxx.md b/src/content/tools/stm32wlxx.md index 62d8897..df0828e 100644 --- a/src/content/tools/stm32wlxx.md +++ b/src/content/tools/stm32wlxx.md @@ -11,9 +11,9 @@ homepage: 'https://github.com/whad-team/stm32wlxx-firmware' software: - whad note: >- - Any STM32WLxx-based board (e.g. Nucleo-WL55JC, Seeed LoRa-E5) — an Arm + Any STM32WLxx-based board (e.g. Nucleo-WL55JC, Seeed LoRa-E5), an Arm Cortex-M4 with an integrated sub-GHz radio. Flashed with WHAD's stm32wlxx-firmware it becomes a WHAD-driven LoRa/LoRaWAN sniff-and-inject radio. --- -Any STM32WLxx-based board (e.g. Nucleo-WL55JC, Seeed LoRa-E5) — an Arm Cortex-M4 with an integrated sub-GHz radio. Flashed with WHAD's stm32wlxx-firmware it becomes a WHAD-driven LoRa/LoRaWAN sniff-and-inject radio. +Any STM32WLxx-based board (e.g. Nucleo-WL55JC, Seeed LoRa-E5), an Arm Cortex-M4 with an integrated sub-GHz radio. Flashed with WHAD's stm32wlxx-firmware it becomes a WHAD-driven LoRa/LoRaWAN sniff-and-inject radio. diff --git a/src/content/tools/ublox-neo-gps.md b/src/content/tools/ublox-neo-gps.md index 6bc9f92..5e32e00 100644 --- a/src/content/tools/ublox-neo-gps.md +++ b/src/content/tools/ublox-neo-gps.md @@ -16,9 +16,9 @@ note: >- The everyday GPS-receiver path: a cheap, common u-blox NEO-class module (NEO-6M / 7 / 8 / 9, often on a USB-serial breakout) that tracks the satellites itself and reports the solved position/time as plain NMEA 0183 - sentences (plus binary UBX). This is how most projects 'get GPS' — no SDR, no + sentences (plus binary UBX). This is how most projects 'get GPS', no SDR, no signal processing on your side; the chip does the acquisition and you just read the serial stream. Use it with an active GPS antenna for a usable fix indoors-adjacent. --- -The everyday GPS-receiver path: a cheap, common u-blox NEO-class module (NEO-6M / 7 / 8 / 9, often on a USB-serial breakout) that tracks the satellites itself and reports the solved position/time as plain NMEA 0183 sentences (plus binary UBX). This is how most projects 'get GPS' — no SDR, no signal processing on your side; the chip does the acquisition and you just read the serial stream. Use it with an active GPS antenna for a usable fix indoors-adjacent. +The everyday GPS-receiver path: a cheap, common u-blox NEO-class module (NEO-6M / 7 / 8 / 9, often on a USB-serial breakout) that tracks the satellites itself and reports the solved position/time as plain NMEA 0183 sentences (plus binary UBX). This is how most projects 'get GPS', no SDR, no signal processing on your side; the chip does the acquisition and you just read the serial stream. Use it with an active GPS antenna for a usable fix indoors-adjacent. diff --git a/src/content/tools/universal-radio-hacker.md b/src/content/tools/universal-radio-hacker.md index 8f451e5..ce8953a 100644 --- a/src/content/tools/universal-radio-hacker.md +++ b/src/content/tools/universal-radio-hacker.md @@ -8,7 +8,7 @@ protocols: repo: 'https://github.com/jopohl/urh' note: >- Integrated reversing workbench: auto-detect modulation/bitrate, extract - bitstreams, diff captures and replay — the fastest path from raw I/Q to a + bitstreams, diff captures and replay, the fastest path from raw I/Q to a labelled frame format. --- -Integrated reversing workbench: auto-detect modulation/bitrate, extract bitstreams, diff captures and replay — the fastest path from raw I/Q to a labelled frame format. +Integrated reversing workbench: auto-detect modulation/bitrate, extract bitstreams, diff captures and replay, the fastest path from raw I/Q to a labelled frame format. diff --git a/src/content/tools/usrp-b210.md b/src/content/tools/usrp-b210.md index bcf06de..44bbcca 100644 --- a/src/content/tools/usrp-b210.md +++ b/src/content/tools/usrp-b210.md @@ -5,7 +5,7 @@ vendor: Ettus Research (NI) type: hardware protocols: - Wide-band SDR -spec: ~56 MHz IBW (30.72 MHz in 2×2) · 70 MHz–6 GHz +spec: ~56 MHz IBW (30.72 MHz in 2×2) · 70 MHz to 6 GHz homepage: 'https://www.ettus.com/all-products/ub210-kit/' software: - ice9-bluetooth-sniffer diff --git a/src/content/tools/whad.md b/src/content/tools/whad.md index 1835c5f..f66ff15 100644 --- a/src/content/tools/whad.md +++ b/src/content/tools/whad.md @@ -12,12 +12,12 @@ protocols: - ESB repo: 'https://github.com/whad-team/whad-client' note: >- - Wireless Hacking Devices — a unified Python framework and host protocol that + Wireless Hacking Devices, a unified Python framework and host protocol that drives many radios to sniff and inject across wireless stacks: BLE, IEEE 802.15.4 / Zigbee / RF4CE, Enhanced ShockBurst, Logitech Unifying, LoRaWAN and a generic PHY layer. Backends include the nRF52840 'Butterfly' firmware, an STM32WLxx (LoRa) firmware, ESP32, Ubertooth, APIMote, RZUSBstick, - RFStorm/nRF24 and Yard Stick One, plus host HCI — one toolchain and PCAP/Scapy + RFStorm/nRF24 and Yard Stick One, plus host HCI, one toolchain and PCAP/Scapy interface across protocols. --- -Wireless Hacking Devices — a unified Python framework and host protocol that drives many radios to sniff and inject across wireless stacks: BLE, IEEE 802.15.4 / Zigbee / RF4CE, Enhanced ShockBurst, Logitech Unifying, LoRaWAN and a generic PHY layer. Backends include the nRF52840 'Butterfly' firmware, an STM32WLxx (LoRa) firmware, ESP32, Ubertooth, APIMote, RZUSBstick, RFStorm/nRF24 and Yard Stick One, plus host HCI — one toolchain and PCAP/Scapy interface across protocols. +Wireless Hacking Devices, a unified Python framework and host protocol that drives many radios to sniff and inject across wireless stacks: BLE, IEEE 802.15.4 / Zigbee / RF4CE, Enhanced ShockBurst, Logitech Unifying, LoRaWAN and a generic PHY layer. Backends include the nRF52840 'Butterfly' firmware, an STM32WLxx (LoRa) firmware, ESP32, Ubertooth, APIMote, RZUSBstick, RFStorm/nRF24 and Yard Stick One, plus host HCI, one toolchain and PCAP/Scapy interface across protocols. diff --git a/src/content/tools/whsniff.md b/src/content/tools/whsniff.md index 224abab..8b12933 100644 --- a/src/content/tools/whsniff.md +++ b/src/content/tools/whsniff.md @@ -10,8 +10,8 @@ repo: 'https://github.com/homewsn/whsniff' software: [] note: >- Command-line utility that interfaces a TI CC2531 USB dongle with Wireshark to - capture and display IEEE 802.15.4 traffic at 2.4 GHz — pipe its output into + capture and display IEEE 802.15.4 traffic at 2.4 GHz, pipe its output into Wireshark (or save a PCAP) for Zigbee dissection. A cheap, simple capture path when you have a CC2531. --- -Command-line utility that interfaces a TI CC2531 USB dongle with Wireshark to capture and display IEEE 802.15.4 traffic at 2.4 GHz — pipe its output into Wireshark (or save a PCAP) for Zigbee dissection. A cheap, simple capture path when you have a CC2531. +Command-line utility that interfaces a TI CC2531 USB dongle with Wireshark to capture and display IEEE 802.15.4 traffic at 2.4 GHz, pipe its output into Wireshark (or save a PCAP) for Zigbee dissection. A cheap, simple capture path when you have a CC2531. diff --git a/src/content/tools/wireshark.md b/src/content/tools/wireshark.md index f653b70..3f95f61 100644 --- a/src/content/tools/wireshark.md +++ b/src/content/tools/wireshark.md @@ -8,7 +8,7 @@ protocols: homepage: 'https://www.wireshark.org' note: >- The universal packet dissector. Capture tools across these protocols export to - PCAP, and Wireshark dissects, decodes and lets you filter the frames here — + PCAP, and Wireshark dissects, decodes and lets you filter the frames here, supplying a network/link key where one is needed to decrypt in place. --- -The universal packet dissector. Capture tools across these protocols export to PCAP, and Wireshark dissects, decodes and lets you filter the frames here — supplying a network/link key where one is needed to decrypt in place. +The universal packet dissector. Capture tools across these protocols export to PCAP, and Wireshark dissects, decodes and lets you filter the frames here, supplying a network/link key where one is needed to decrypt in place. diff --git a/src/content/tools/yard-stick-one.md b/src/content/tools/yard-stick-one.md index 4cec3b1..859ad00 100644 --- a/src/content/tools/yard-stick-one.md +++ b/src/content/tools/yard-stick-one.md @@ -10,8 +10,8 @@ software: - rfcat - universal-radio-hacker note: >- - CC1111 sub-GHz transceiver (300–928 MHz) driven by rfcat — receive, replay and + CC1111 sub-GHz transceiver (300 to 928 MHz) driven by rfcat, receive, replay and transmit OOK/ASK/FSK from a Python shell. The reference cheap Sub-GHz work tool, paired with a HackRF for discovery. --- -CC1111 sub-GHz transceiver (300–928 MHz) driven by rfcat — receive, replay and transmit OOK/ASK/FSK from a Python shell. The reference cheap Sub-GHz work tool, paired with a HackRF for discovery. +CC1111 sub-GHz transceiver (300 to 928 MHz) driven by rfcat, receive, replay and transmit OOK/ASK/FSK from a Python shell. The reference cheap Sub-GHz work tool, paired with a HackRF for discovery. diff --git a/src/content/tools/zbdsniff.md b/src/content/tools/zbdsniff.md index 92a0adf..1e8b3b9 100644 --- a/src/content/tools/zbdsniff.md +++ b/src/content/tools/zbdsniff.md @@ -10,8 +10,8 @@ software: [] note: >- KillerBee's key-extraction tool. Scans a capture for an over-the-air key transport (APS Transport-Key during a device join) and recovers the Zigbee - network key — the classic break when the key is sent under the well-known + network key, the classic break when the key is sent under the well-known default Trust Center link key 'ZigBeeAlliance09'. Feed it a PCAP of a join and it prints the network key. --- -KillerBee's key-extraction tool. Scans a capture for an over-the-air key transport (APS Transport-Key during a device join) and recovers the Zigbee network key — the classic break when the key is sent under the well-known default Trust Center link key 'ZigBeeAlliance09'. Feed it a PCAP of a join and it prints the network key. +KillerBee's key-extraction tool. Scans a capture for an over-the-air key transport (APS Transport-Key during a device join) and recovers the Zigbee network key, the classic break when the key is sent under the well-known default Trust Center link key 'ZigBeeAlliance09'. Feed it a PCAP of a join and it prints the network key. diff --git a/src/content/tools/zwave-pc-controller.md b/src/content/tools/zwave-pc-controller.md index f64e6d2..6cab8a3 100644 --- a/src/content/tools/zwave-pc-controller.md +++ b/src/content/tools/zwave-pc-controller.md @@ -11,7 +11,7 @@ note: >- Silicon Labs' official GUI controller (Simplicity Studio): implements a Z-Wave controller node over the Serial API of a UZB USB adapter, so you can include/exclude nodes, browse the device's supported command classes and send - them — driving a Z-Wave network legitimately from a PC. The application-layer + them, driving a Z-Wave network legitimately from a PC. The application-layer counterpart to the Zniffer's capture. --- -Silicon Labs' official GUI controller (Simplicity Studio): implements a Z-Wave controller node over the Serial API of a UZB USB adapter, so you can include/exclude nodes, browse the device's supported command classes and send them — driving a Z-Wave network legitimately from a PC. The application-layer counterpart to the Zniffer's capture. +Silicon Labs' official GUI controller (Simplicity Studio): implements a Z-Wave controller node over the Serial API of a UZB USB adapter, so you can include/exclude nodes, browse the device's supported command classes and send them, driving a Z-Wave network legitimately from a PC. The application-layer counterpart to the Zniffer's capture. diff --git a/src/content/tools/zwave-zniffer.md b/src/content/tools/zwave-zniffer.md index 01d868d..ff5603d 100644 --- a/src/content/tools/zwave-zniffer.md +++ b/src/content/tools/zwave-zniffer.md @@ -9,9 +9,9 @@ homepage: 'https://docs.silabs.com/z-wave/1.0.1/z-wave-docs/zwave-tools' software: [] note: >- Silicon Labs' official GUI tool (in Simplicity Studio) that captures RF - communication on a Z-Wave network for debugging — the vendor sniffer. Decodes + communication on a Z-Wave network for debugging, the vendor sniffer. Decodes the full Z-Wave frame including command classes and shows security (S0/S2) handshakes. Needs a USB Z-Wave adapter flashed with Zniffer firmware (e.g. a UZB stick). The turnkey capture path when an SDR demod is too fiddly. --- -Silicon Labs' official GUI tool (in Simplicity Studio) that captures RF communication on a Z-Wave network for debugging — the vendor sniffer. Decodes the full Z-Wave frame including command classes and shows security (S0/S2) handshakes. Needs a USB Z-Wave adapter flashed with Zniffer firmware (e.g. a UZB stick). The turnkey capture path when an SDR demod is too fiddly. +Silicon Labs' official GUI tool (in Simplicity Studio) that captures RF communication on a Z-Wave network for debugging, the vendor sniffer. Decodes the full Z-Wave frame including command classes and shows security (S0/S2) handshakes. Needs a USB Z-Wave adapter flashed with Zniffer firmware (e.g. a UZB stick). The turnkey capture path when an SDR demod is too fiddly. diff --git a/src/data/protocol-tools/adsb.json b/src/data/protocol-tools/adsb.json index 3204c10..083cacd 100644 --- a/src/data/protocol-tools/adsb.json +++ b/src/data/protocol-tools/adsb.json @@ -33,7 +33,7 @@ "type": "software", "protocols": ["ADS-B"], "repo": "https://github.com/bistromath/gr-air-modes", - "note": "A GNU Radio Mode S / ADS-B receiver: a flowgraph that demodulates 1090 MHz and decodes the Extended Squitter, with a live map output. The choice when you want the signal inside a GNU Radio flowgraph to see and modify each DSP block rather than a black-box decoder. Older codebase (last active ~2021) — a learning/DSP receiver rather than a polished aggregator." + "note": "A GNU Radio Mode S / ADS-B receiver: a flowgraph that demodulates 1090 MHz and decodes the Extended Squitter, with a live map output. The choice when you want the signal inside a GNU Radio flowgraph to see and modify each DSP block rather than a black-box decoder. Older codebase (last active ~2021), a learning/DSP receiver rather than a polished aggregator." }, { "slug": "tar1090", @@ -51,7 +51,7 @@ "type": "project", "protocols": ["ADS-B"], "repo": "https://github.com/lyusupov/ADSB-Out", - "note": "A Python encoder that builds forged 1090ES ADS-B Extended Squitter frames (chosen ICAO address, position, altitude) into an I/Q sample file for transmission by a TX-capable SDR (HackRF via hackrf_transfer). The concrete way to demonstrate ADS-B spoofing/injection — there is no authentication on the link, so a higher-power forged frame is accepted as a real aircraft. Author states it is for academic purposes only. AUTHORIZED, RF-CONTAINED testing only: never radiate on-air — use a shielded enclosure or a conducted (cabled) setup. Stable but inactive (last commit ~2021)." + "note": "A Python encoder that builds forged 1090ES ADS-B Extended Squitter frames (chosen ICAO address, position, altitude) into an I/Q sample file for transmission by a TX-capable SDR (HackRF via hackrf_transfer). The concrete way to demonstrate ADS-B spoofing/injection, there is no authentication on the link, so a higher-power forged frame is accepted as a real aircraft. Author states it is for academic purposes only. AUTHORIZED, RF-CONTAINED testing only: never radiate on-air, use a shielded enclosure or a conducted (cabled) setup. Stable but inactive (last commit ~2021)." }, { "slug": "pymodes", @@ -60,6 +60,6 @@ "type": "software", "protocols": ["ADS-B"], "repo": "https://github.com/junzis/pyModeS", - "note": "A pure-Python decoder library for Mode S and ADS-B messages: feed it hex frames (or stream them from dump1090 over TCP/Beast) and it returns the decoded fields — ICAO address, callsign, airborne/surface position (CPR), velocity, altitude — plus DF4/5/11/20/21 surveillance and Comm-B BDS registers. The reference way to interpret message contents and to run plausibility / anti-spoof checks on a decoded feed in your own code." + "note": "A pure-Python decoder library for Mode S and ADS-B messages: feed it hex frames (or stream them from dump1090 over TCP/Beast) and it returns the decoded fields, ICAO address, callsign, airborne/surface position (CPR), velocity, altitude, plus DF4/5/11/20/21 surveillance and Comm-B BDS registers. The reference way to interpret message contents and to run plausibility / anti-spoof checks on a decoded feed in your own code." } ] diff --git a/src/data/protocol-tools/esp32.json b/src/data/protocol-tools/esp32.json index 541be91..5aea6a3 100644 --- a/src/data/protocol-tools/esp32.json +++ b/src/data/protocol-tools/esp32.json @@ -4,7 +4,7 @@ "protocols": ["Wi-Fi", "BLE", "Bluetooth Classic"], "spec": "Xtensa LX6 dual-core · 2.4 GHz Wi-Fi b/g/n · Bluetooth Classic (BR/EDR) + BLE 4.2", "software": ["esp32-marauder", "bruce", "ghost-esp", "esp32-wifi-penetration-tool", "esp32-deauther-ganesh", "esp32-bt-classic-sniffer", "braktooth", "esp32-bluejammer"], - "note": "The generic original ESP32 dev board (WROOM-32 / WROVER module) — the cheapest substrate for the umbrella firmwares (Marauder, Bruce, Ghost ESP) and the bare-metal Wi-Fi/BLE tools. Crucially, the ORIGINAL ESP32 is the only variant with a Bluetooth Classic (BR/EDR) radio, so it is also the board the BR/EDR sniffer and BrakTooth PoC run on. A bare board with no screen or SD — add a microSD for capture-to-card firmwares. 2.4 GHz only (no 5/6 GHz)." + "note": "The generic original ESP32 dev board (WROOM-32 / WROVER module), the cheapest substrate for the umbrella firmwares (Marauder, Bruce, Ghost ESP) and the bare-metal Wi-Fi/BLE tools. Crucially, the ORIGINAL ESP32 is the only variant with a Bluetooth Classic (BR/EDR) radio, so it is also the board the BR/EDR sniffer and BrakTooth PoC run on. A bare board with no screen or SD, add a microSD for capture-to-card firmwares. 2.4 GHz only (no 5/6 GHz)." }, { "slug": "esp32-s3-devkit", "name": "ESP32-S3 DevKitC", "vendor": "Espressif", "type": "hardware", @@ -12,15 +12,15 @@ "spec": "Xtensa LX7 dual-core · 2.4 GHz Wi-Fi · Bluetooth 5 (LE) · native USB-OTG", "homepage": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/hw-reference/esp32s3/user-guide-devkitc-1.html", "software": ["esp32-marauder", "bruce", "ghost-esp", "esp32-sour-apple", "esp32-airtag-scanner"], - "note": "Espressif's ESP32-S3: LX7 dual-core with Bluetooth 5 (LE), native USB-OTG and more RAM than the original ESP32 — which is why most modern handheld pentest boards (Cardputer, LilyGo T-series) are S3-based. Supported by Marauder, Bruce and Ghost ESP, and the BLE-capable target for the focused BLE tools. Note: the S3 has BLE but NO Bluetooth Classic radio — for BR/EDR work use the original ESP32." + "note": "Espressif's ESP32-S3: LX7 dual-core with Bluetooth 5 (LE), native USB-OTG and more RAM than the original ESP32, which is why most modern handheld pentest boards (Cardputer, LilyGo T-series) are S3-based. Supported by Marauder, Bruce and Ghost ESP, and the BLE-capable target for the focused BLE tools. Note: the S3 has BLE but NO Bluetooth Classic radio, for BR/EDR work use the original ESP32." }, { - "slug": "cyd", "name": "CYD — Cheap Yellow Display (ESP32-2432S028R)", "vendor": "community (Witnessmenow guide)", "type": "hardware", + "slug": "cyd", "name": "CYD, Cheap Yellow Display (ESP32-2432S028R)", "vendor": "community (Witnessmenow guide)", "type": "hardware", "protocols": ["Wi-Fi", "BLE", "Bluetooth Classic"], "spec": "ESP32-WROOM-32 · 2.8\" 240×320 resistive-touch TFT · microSD · ~$15", "repo": "https://github.com/witnessmenow/ESP32-Cheap-Yellow-Display", "software": ["esp32-marauder", "bruce", "ghost-esp"], - "note": "The ~$15 'Cheap Yellow Display': an ESP32-WROOM-32 board with a built-in 2.8\" touch TFT, microSD and USB-UART. Hugely popular as a cheap touchscreen pentest handheld — runs ESP32 Marauder (and CYD-specific forks), Bruce and Ghost ESP with a usable on-screen UI and no soldering. The linked repo is the community hardware/pinout reference." + "note": "The ~$15 'Cheap Yellow Display': an ESP32-WROOM-32 board with a built-in 2.8\" touch TFT, microSD and USB-UART. Hugely popular as a cheap touchscreen pentest handheld, runs ESP32 Marauder (and CYD-specific forks), Bruce and Ghost ESP with a usable on-screen UI and no soldering. The linked repo is the community hardware/pinout reference." }, { "slug": "m5-cardputer", "name": "M5Stack Cardputer", "vendor": "M5Stack", "type": "hardware", @@ -28,15 +28,15 @@ "spec": "M5StampS3 (ESP32-S3) · 56-key keyboard · 1.14\" LCD · microSD · IR · battery", "homepage": "https://docs.m5stack.com/en/core/Cardputer", "software": ["esp32-marauder", "bruce", "ghost-esp"], - "note": "Pocket keyboard-computer on the M5StampS3 (ESP32-S3): full keyboard, LCD, microSD, IR and battery in a card-sized case. A pentest-community favourite chassis — runs ESP32 Marauder, Bruce and Ghost ESP out of the box (Marauder added Cardputer ADV support in v1.12.0). Bruce's flagship target." + "note": "Pocket keyboard-computer on the M5StampS3 (ESP32-S3): full keyboard, LCD, microSD, IR and battery in a card-sized case. A pentest-community favourite chassis, runs ESP32 Marauder, Bruce and Ghost ESP out of the box (Marauder added Cardputer ADV support in v1.12.0). Bruce's flagship target." }, { "slug": "flipper-wifi-devboard", "name": "Flipper Zero Wi-Fi Dev Board", "vendor": "Flipper Devices", "type": "hardware", "protocols": ["Wi-Fi"], - "spec": "ESP32-S2-WROVER · 2.4 GHz Wi-Fi only — S2 has NO Bluetooth radio", + "spec": "ESP32-S2-WROVER · 2.4 GHz Wi-Fi only, S2 has NO Bluetooth radio", "homepage": "https://flipper.net/products/wifi-devboard", "software": ["esp32-marauder"], - "note": "Official Flipper Zero add-on built on an ESP32-S2-WROVER. Sold for wireless firmware flashing / debugging, but the community flashes ESP32 Marauder onto it to give the Flipper a Wi-Fi attack add-on (deauth, beacon spam, Evil Portal). Because the S2 has no Bluetooth radio, the BLE features are NOT available on this board — it is Wi-Fi only." + "note": "Official Flipper Zero add-on built on an ESP32-S2-WROVER. Sold for wireless firmware flashing / debugging, but the community flashes ESP32 Marauder onto it to give the Flipper a Wi-Fi attack add-on (deauth, beacon spam, Evil Portal). Because the S2 has no Bluetooth radio, the BLE features are NOT available on this board, it is Wi-Fi only." }, { "slug": "lilygo-t-embed-cc1101", "name": "LilyGo T-Embed CC1101", "vendor": "LilyGo", "type": "hardware", @@ -51,7 +51,7 @@ "slug": "esp32-marauder", "name": "ESP32 Marauder", "vendor": "justcallmekoko", "type": "project", "protocols": ["Wi-Fi", "BLE"], "repo": "https://github.com/justcallmekoko/ESP32Marauder", - "note": "The reference ESP32 Wi-Fi + BLE offensive/defensive firmware (~11k stars, actively maintained). Wi-Fi: scan APs/stations, packet sniff, GPS wardrive, deauth, beacon spam (list/random), probe-request flood, EAPOL/PMKID capture to SD, and an Evil Portal captive-portal credential harvester. BLE: scan/sniff, wardrive, AirTag sniff and spoof, and advertising spam (Apple/Sour Apple, Samsung, Swift Pair). Runs on ESP32/S2/S3/C5 and 20+ boards (Cardputer, CYD, Flipper Wi-Fi dev board) — but NOT the ESP32-C6. 2.4 GHz only. Representative of the ESP32 attack surface — authorised testing only on active features." + "note": "The reference ESP32 Wi-Fi + BLE offensive/defensive firmware (~11k stars, actively maintained). Wi-Fi: scan APs/stations, packet sniff, GPS wardrive, deauth, beacon spam (list/random), probe-request flood, EAPOL/PMKID capture to SD, and an Evil Portal captive-portal credential harvester. BLE: scan/sniff, wardrive, AirTag sniff and spoof, and advertising spam (Apple/Sour Apple, Samsung, Swift Pair). Runs on ESP32/S2/S3/C5 and 20+ boards (Cardputer, CYD, Flipper Wi-Fi dev board), but NOT the ESP32-C6. 2.4 GHz only. Representative of the ESP32 attack surface, authorised testing only on active features." }, { "slug": "bruce", "name": "Bruce", "vendor": "BruceDevices (pr3y)", "type": "project", @@ -69,84 +69,84 @@ "slug": "esp32-wifi-penetration-tool", "name": "ESP32 Wi-Fi Penetration Tool", "vendor": "risinek", "type": "project", "protocols": ["Wi-Fi"], "repo": "https://github.com/risinek/esp32-wifi-penetration-tool", - "note": "Focused ESP-IDF framework for ESP32 Wi-Fi attacks (~2.9k stars, MIT, last push 2024-02). Captures WPA/WPA2 PMKIDs and 4-way handshakes (passively, via a rogue duplicate AP, or by forcing re-auth), formats captures to PCAP and converts them to a hashcat-ready HCCAPX; also runs deauthentication and DoS attacks. Driven entirely from an on-device management-AP web UI — no screen needed. Includes a WSL bypasser to emit arbitrary 802.11 frames on a plain ESP32." + "note": "Focused ESP-IDF framework for ESP32 Wi-Fi attacks (~2.9k stars, MIT, last push 2024-02). Captures WPA/WPA2 PMKIDs and 4-way handshakes (passively, via a rogue duplicate AP, or by forcing re-auth), formats captures to PCAP and converts them to a hashcat-ready HCCAPX; also runs deauthentication and DoS attacks. Driven entirely from an on-device management-AP web UI, no screen needed. Includes a WSL bypasser to emit arbitrary 802.11 frames on a plain ESP32." }, { "slug": "esp32-deauther-ganesh", "name": "ESP32 Deauther (GANESH-ICMC)", "vendor": "GANESH-ICMC", "type": "project", "protocols": ["Wi-Fi"], "repo": "https://github.com/GANESH-ICMC/esp32-deauther", - "note": "An ESP-IDF port of the Spacehuhn deauther to the ESP32, built on the esp_wifi_80211_tx frame-injection function — the canonical bare-ESP32 deauth path referenced by risinek's penetration tool. NOTE: unmaintained since 2021 and ships no license file; confirm it builds against a current ESP-IDF before relying on it. (The famous Spacehuhn esp8266_deauther is ESP8266-only and does not run on the ESP32.)" + "note": "An ESP-IDF port of the Spacehuhn deauther to the ESP32, built on the esp_wifi_80211_tx frame-injection function, the canonical bare-ESP32 deauth path referenced by risinek's penetration tool. NOTE: unmaintained since 2021 and ships no license file; confirm it builds against a current ESP-IDF before relying on it. (The famous Spacehuhn esp8266_deauther is ESP8266-only and does not run on the ESP32.)" }, { "slug": "esp32-projectzero", "name": "projectZero", "vendor": "LOCOSP", "type": "project", "protocols": ["Wi-Fi"], "repo": "https://github.com/LOCOSP/projectZero", - "note": "A two-board ESP32 evil-twin / deauther whose captive portal VERIFIES the entered password against the real AP, plus a WPA3-SAE overflow mode (MIT, active but small/early). Runs on ESP32 and ESP32-C5, driven from a CLI or a Flipper Zero. Low-maturity project — verify its behaviour on the bench before field use; the password-verifying portal and SAE-overflow angle are what make it worth noting." + "note": "A two-board ESP32 evil-twin / deauther whose captive portal VERIFIES the entered password against the real AP, plus a WPA3-SAE overflow mode (MIT, active but small/early). Runs on ESP32 and ESP32-C5, driven from a CLI or a Flipper Zero. Low-maturity project, verify its behaviour on the bench before field use; the password-verifying portal and SAE-overflow angle are what make it worth noting." }, { "slug": "esp32-sour-apple", "name": "ESP32 Sour Apple", "vendor": "RapierXbox", "type": "project", "protocols": ["BLE"], "repo": "https://github.com/RapierXbox/ESP32-Sour-Apple", - "note": "A focused PoC that crashes/freezes iOS devices by flooding them with BLE pairing-request advertisements (~595 stars, GPL-3.0). Tested on ESP32-S3 and ESP-WROOM-32 (an ESP8266 cannot run it — no BLE radio). Genuinely disruptive — it can freeze nearby iPhones — so authorised testing only, on hardware you own. Target/payload effectiveness dates as Apple patches." + "note": "A focused PoC that crashes/freezes iOS devices by flooding them with BLE pairing-request advertisements (~595 stars, GPL-3.0). Tested on ESP32-S3 and ESP-WROOM-32 (an ESP8266 cannot run it, no BLE radio). Genuinely disruptive, it can freeze nearby iPhones, so authorised testing only, on hardware you own. Target/payload effectiveness dates as Apple patches." }, { "slug": "evilapplejuice-esp32", "name": "EvilAppleJuice-ESP32", "vendor": "ckcr4lyf", "type": "project", "protocols": ["BLE"], "repo": "https://github.com/ckcr4lyf/EvilAppleJuice-ESP32", - "note": "A self-contained ESP32 sketch that spams Apple BLE proximity-pairing messages — the 'connect AirPods / setup' style popups — on nearby iOS devices (~2.1k stars). Single-purpose Apple advertising spam, derived from the AppleJuice proximity-spoof research. Authorised testing only; disruptive to all nearby Apple devices." + "note": "A self-contained ESP32 sketch that spams Apple BLE proximity-pairing messages, the 'connect AirPods / setup' style popups, on nearby iOS devices (~2.1k stars). Single-purpose Apple advertising spam, derived from the AppleJuice proximity-spoof research. Authorised testing only; disruptive to all nearby Apple devices." }, { "slug": "applejuice", "name": "AppleJuice", "vendor": "ECTO-1A", "type": "project", "protocols": ["BLE"], "repo": "https://github.com/ECTO-1A/AppleJuice", - "note": "The original Apple BLE proximity-pairing message-spoofing research/PoC (~1.9k stars, Apache-2.0, last push 2024-06) — the upstream source of the 'Apple BLE spam' payloads reused by Marauder, Bruce, Ghost ESP and EvilAppleJuice. A reference corpus rather than a polished tool; payloads date as Apple patches, so treat as representative, not current." + "note": "The original Apple BLE proximity-pairing message-spoofing research/PoC (~1.9k stars, Apache-2.0, last push 2024-06), the upstream source of the 'Apple BLE spam' payloads reused by Marauder, Bruce, Ghost ESP and EvilAppleJuice. A reference corpus rather than a polished tool; payloads date as Apple patches, so treat as representative, not current." }, { "slug": "esp32-airtag-scanner", "name": "ESP32 AirTag Scanner", "vendor": "MatthewKuKanich", "type": "project", "protocols": ["BLE"], "repo": "https://github.com/MatthewKuKanich/ESP32-AirTag-Scanner", - "note": "ESP32 firmware that scans for Apple AirTag / Find My MAC addresses and BLE payloads without an Android phone or nRF Connect (~110 stars, last push 2024-04). Passive scan only — no spoofing or emulation; output over UART. Supports ESP32-WROOM and ESP32-S3. Useful at the survey step to detect trackers in the environment." + "note": "ESP32 firmware that scans for Apple AirTag / Find My MAC addresses and BLE payloads without an Android phone or nRF Connect (~110 stars, last push 2024-04). Passive scan only, no spoofing or emulation; output over UART. Supports ESP32-WROOM and ESP32-S3. Useful at the survey step to detect trackers in the environment." }, { "slug": "openhaystack", "name": "OpenHaystack", "vendor": "SEEMOO Lab (TU Darmstadt)", "type": "project", "protocols": ["BLE"], "repo": "https://github.com/seemoo-lab/openhaystack", - "note": "Academic framework for tracking personal BLE devices via Apple's Find My network (~13k stars, AGPL-3.0). It ships ESP32 (and nRF51822) firmware that advertises as a Find My beacon, so an ESP32 can act as a DIY 'AirTag' — the AirTag/Find-My beacon spoof/emulation path on cheap hardware. Authorised research only; covertly placing a Find My beacon to track a person is unlawful." + "note": "Academic framework for tracking personal BLE devices via Apple's Find My network (~13k stars, AGPL-3.0). It ships ESP32 (and nRF51822) firmware that advertises as a Find My beacon, so an ESP32 can act as a DIY 'AirTag', the AirTag/Find-My beacon spoof/emulation path on cheap hardware. Authorised research only; covertly placing a Find My beacon to track a person is unlawful." }, { "slug": "esp32-bt-classic-sniffer", "name": "ESP32 Bluetooth Classic Sniffer", "vendor": "Matheus Garbelini", "type": "software", "protocols": ["Bluetooth Classic"], "repo": "https://github.com/Matheus-Garbelini/esp32_bluetooth_classic_sniffer", - "note": "The reference active BR/EDR sniffer on commodity ESP32 hardware (~$4–10; ~590 stars, GPL-2.0). It patches the ESP32 ROM Bluetooth stack to dump baseband packets — BT header, channel, device role, FHS, ACL and LMP — over USB serial to a host Python tool (BTSnifferBREDR.py) with Scapy/Wireshark output. This is Bluetooth CLASSIC (BR/EDR), not BLE. It actively connects to the target, so authorised testing only." + "note": "The reference active BR/EDR sniffer on commodity ESP32 hardware (~$4 to 10; ~590 stars, GPL-2.0). It patches the ESP32 ROM Bluetooth stack to dump baseband packets, BT header, channel, device role, FHS, ACL and LMP, over USB serial to a host Python tool (BTSnifferBREDR.py) with Scapy/Wireshark output. This is Bluetooth CLASSIC (BR/EDR), not BLE. It actively connects to the target, so authorised testing only." }, { "slug": "braktooth", "name": "BrakTooth (ESP32 PoC)", "vendor": "Matheus Garbelini", "type": "project", "protocols": ["Bluetooth Classic"], "repo": "https://github.com/Matheus-Garbelini/braktooth_esp32_bluetooth_classic_attacks", - "note": "The public PoC release for the BrakTooth family of Bluetooth Classic baseband/LMP vulnerabilities — roughly 16 CVEs and 20+ attack variants against the BR/EDR controllers of dozens of SoCs (Espressif ESP32, Intel AX200, Qualcomm, Cypress/Infineon, TI CC2564 and more). Built on the patched-ESP32 sniffer; the attacks range from crash/DoS to, on some targets, RCE. Representative — check vendor advisories for current patch status. Authorised testing only, against devices you own or are contracted to assess." + "note": "The public PoC release for the BrakTooth family of Bluetooth Classic baseband/LMP vulnerabilities, roughly 16 CVEs and 20+ attack variants against the BR/EDR controllers of dozens of SoCs (Espressif ESP32, Intel AX200, Qualcomm, Cypress/Infineon, TI CC2564 and more). Built on the patched-ESP32 sniffer; the attacks range from crash/DoS to, on some targets, RCE. Representative, check vendor advisories for current patch status. Authorised testing only, against devices you own or are contracted to assess." }, { "slug": "esp32-classic-bt-scan", "name": "ClassicBTScan", "vendor": "AntorFr", "type": "software", "protocols": ["Bluetooth Classic"], "repo": "https://github.com/AntorFr/ClassicBTScan", - "note": "A small Arduino-ESP32 library that performs a true Bluetooth Classic (BR/EDR) inquiry scan via the Bluedroid GAP API — returning each discovered device's MAC address, name, RSSI and Class-of-Device (CoD). The BR/EDR analogue of a BLE advertising scan (MIT, last push 2020). Only finds devices in discoverable / inquiry-scan mode; pin it to a known ESP-IDF as it is unmaintained." + "note": "A small Arduino-ESP32 library that performs a true Bluetooth Classic (BR/EDR) inquiry scan via the Bluedroid GAP API, returning each discovered device's MAC address, name, RSSI and Class-of-Device (CoD). The BR/EDR analogue of a BLE advertising scan (MIT, last push 2020). Only finds devices in discoverable / inquiry-scan mode; pin it to a known ESP-IDF as it is unmaintained." }, { "slug": "esp32-bt-exp", "name": "ESP32-BT-exp", "vendor": "esp32beans", "type": "software", "protocols": ["Bluetooth Classic", "BLE"], "repo": "https://github.com/esp32beans/ESP32-BT-exp", - "note": "An Arduino-ESP32 sketch that brings up the Bluedroid stack in dual-mode (Classic + BLE) and dumps discovered devices in pairing/inquiry mode (MIT). Discovery only — no pairing or connection. Classic (BR/EDR) discovery needs the original ESP32, not the C-series, which has no Bluetooth Classic radio." + "note": "An Arduino-ESP32 sketch that brings up the Bluedroid stack in dual-mode (Classic + BLE) and dumps discovered devices in pairing/inquiry mode (MIT). Discovery only, no pairing or connection. Classic (BR/EDR) discovery needs the original ESP32, not the C-series, which has no Bluetooth Classic radio." }, { "slug": "esp32-bluejammer", "name": "ESP32 BlueJammer", "vendor": "EmenstaNougat", "type": "project", "protocols": ["Bluetooth Classic", "BLE", "Wi-Fi"], "repo": "https://github.com/EmenstaNougat/ESP32-BlueJammer", - "note": "An ESP32 driving two nRF24L01+PA+LNA modules to flood the 2.4 GHz ISM band with noise, hopping channels to disrupt Bluetooth Classic (79 ch), BLE (40 ch), Wi-Fi (14 ch) and 2.4 GHz RC/drone links. WARNING: RF jamming is illegal in most jurisdictions (e.g. unlawful in the US under FCC rules) — use only in an RF-shielded / controlled environment for authorised resilience testing. Requires two nRF24L01+PA+LNA modules in addition to the ESP32." + "note": "An ESP32 driving two nRF24L01+PA+LNA modules to flood the 2.4 GHz ISM band with noise, hopping channels to disrupt Bluetooth Classic (79 ch), BLE (40 ch), Wi-Fi (14 ch) and 2.4 GHz RC/drone links. WARNING: RF jamming is illegal in most jurisdictions (e.g. unlawful in the US under FCC rules), use only in an RF-shielded / controlled environment for authorised resilience testing. Requires two nRF24L01+PA+LNA modules in addition to the ESP32." }, { "slug": "marauder-ui-android-app", "name": "Marauder UI (Android)", "vendor": "Electronic Cats", "type": "software", "ec": true, "protocols": ["Wi-Fi", "BLE"], "repo": "https://github.com/ElectronicCats/marauder-ui-android-app", - "note": "Electronic Cats' Android companion app that drives an ESP32 Marauder board over a phone UI instead of the on-device screen. A host front-end for the Marauder firmware (not a firmware or a board itself) — the EC tie-in to the ESP32 Marauder ecosystem." + "note": "Electronic Cats' Android companion app that drives an ESP32 Marauder board over a phone UI instead of the on-device screen. A host front-end for the Marauder firmware (not a firmware or a board itself), the EC tie-in to the ESP32 Marauder ecosystem." } ] diff --git a/src/data/protocol-tools/gnss.json b/src/data/protocol-tools/gnss.json index 4515f7d..1ff9ba9 100644 --- a/src/data/protocol-tools/gnss.json +++ b/src/data/protocol-tools/gnss.json @@ -7,7 +7,7 @@ "protocols": ["GNSS"], "repo": "https://github.com/gnss-sdr/gnss-sdr", "homepage": "https://gnss-sdr.org", - "note": "Open-source software-defined GNSS receiver. Takes raw L-band I/Q from an SDR and runs the full receive chain — acquisition, tracking, telemetry decoding of the navigation message, and PVT (position/velocity/time) computation — for GPS L1/L2/L5, Galileo, GLONASS and BeiDou. The reference way to receive and decode a live civilian GNSS signal in software." + "note": "Open-source software-defined GNSS receiver. Takes raw L-band I/Q from an SDR and runs the full receive chain, acquisition, tracking, telemetry decoding of the navigation message, and PVT (position/velocity/time) computation, for GPS L1/L2/L5, Galileo, GLONASS and BeiDou. The reference way to receive and decode a live civilian GNSS signal in software." }, { "slug": "gps-sdr-sim", @@ -16,7 +16,7 @@ "type": "software", "protocols": ["GNSS"], "repo": "https://github.com/osqzss/gps-sdr-sim", - "note": "Generates a GPS L1 C/A baseband I/Q file from a RINEX broadcast ephemeris and a chosen static or moving position, for transmission by an SDR (HackRF / bladeRF / USRP). Because civilian C/A is unauthenticated, a replayed/synthesised signal at higher power can pull a receiver's position and clock to attacker-chosen values — the canonical GPS spoofing tool. AUTHORIZED, RF-CONTAINED testing only: transmitting GPS over the air is illegal in most jurisdictions — use a shielded enclosure or a cabled (conducted) setup. Repo is archived but remains the de-facto reference." + "note": "Generates a GPS L1 C/A baseband I/Q file from a RINEX broadcast ephemeris and a chosen static or moving position, for transmission by an SDR (HackRF / bladeRF / USRP). Because civilian C/A is unauthenticated, a replayed/synthesised signal at higher power can pull a receiver's position and clock to attacker-chosen values, the canonical GPS spoofing tool. AUTHORIZED, RF-CONTAINED testing only: transmitting GPS over the air is illegal in most jurisdictions, use a shielded enclosure or a cabled (conducted) setup. Repo is archived but remains the de-facto reference." }, { "slug": "ublox-neo-gps", @@ -27,7 +27,7 @@ "homepage": "https://www.u-blox.com/en/product/neo-m9n-module", "spec": "L1 GNSS receiver module (GPS/GLONASS/Galileo/BeiDou); USB or UART/serial; NMEA 0183 + UBX output", "software": ["gpsd", "u-center"], - "note": "The everyday GPS-receiver path: a cheap, common u-blox NEO-class module (NEO-6M / 7 / 8 / 9, often on a USB-serial breakout) that tracks the satellites itself and reports the solved position/time as plain NMEA 0183 sentences (plus binary UBX). This is how most projects 'get GPS' — no SDR, no signal processing on your side; the chip does the acquisition and you just read the serial stream. Use it with an active GPS antenna for a usable fix indoors-adjacent." + "note": "The everyday GPS-receiver path: a cheap, common u-blox NEO-class module (NEO-6M / 7 / 8 / 9, often on a USB-serial breakout) that tracks the satellites itself and reports the solved position/time as plain NMEA 0183 sentences (plus binary UBX). This is how most projects 'get GPS', no SDR, no signal processing on your side; the chip does the acquisition and you just read the serial stream. Use it with an active GPS antenna for a usable fix indoors-adjacent." }, { "slug": "gpsd", @@ -37,7 +37,7 @@ "protocols": ["GNSS"], "repo": "https://gitlab.com/gpsd/gpsd", "homepage": "https://gpsd.io/", - "note": "The GPS service daemon: it reads the NMEA 0183 / UBX stream from a GNSS receiver on a serial or USB port, parses it, and re-serves the solved position/velocity/time to clients over a simple TCP/JSON protocol — with gpsmon and cgps for live terminal display of the fix, satellites and raw sentences. The standard way to consume a real GPS receiver on Linux/BSD and the normal 'see what the receiver reports' tool. Hosted on GitLab/Savannah, not GitHub." + "note": "The GPS service daemon: it reads the NMEA 0183 / UBX stream from a GNSS receiver on a serial or USB port, parses it, and re-serves the solved position/velocity/time to clients over a simple TCP/JSON protocol, with gpsmon and cgps for live terminal display of the fix, satellites and raw sentences. The standard way to consume a real GPS receiver on Linux/BSD and the normal 'see what the receiver reports' tool. Hosted on GitLab/Savannah, not GitHub." }, { "slug": "u-center", diff --git a/src/data/protocol-tools/gsm.json b/src/data/protocol-tools/gsm.json index e57d044..1804d29 100644 --- a/src/data/protocol-tools/gsm.json +++ b/src/data/protocol-tools/gsm.json @@ -23,7 +23,7 @@ "vendor": "Oros42", "type": "software", "protocols": ["GSM"], - "note": "Python tool that reads the GSMTAP stream produced by gr-gsm and pulls the IMSI / TMSI identities the network pages over the air, printing the cellphones it sees around you. A PASSIVE IMSI catcher — it harvests identities off the broadcast/control channels without transmitting anything (no rogue cell); the active catcher is a rogue BTS (osmo-bts / OpenBTS).", + "note": "Python tool that reads the GSMTAP stream produced by gr-gsm and pulls the IMSI / TMSI identities the network pages over the air, printing the cellphones it sees around you. A PASSIVE IMSI catcher, it harvests identities off the broadcast/control channels without transmitting anything (no rogue cell); the active catcher is a rogue BTS (osmo-bts / OpenBTS).", "repo": "https://github.com/Oros42/IMSI-catcher" }, { @@ -34,7 +34,7 @@ "protocols": ["GSM"], "spec": "osmo-trx + osmo-bts + osmo-bsc + osmo-msc + osmo-hlr", "repo": "https://github.com/osmocom/osmo-bts", - "note": "The Osmocom open GSM network stack: osmo-trx drives the SDR, osmo-bts is the base station, with osmo-bsc / osmo-msc / osmo-hlr forming the core. Together they stand up a full 2G cell on an SDR — the reference open platform for a test/rogue BTS and active IMSI-catcher research. Actively maintained." + "note": "The Osmocom open GSM network stack: osmo-trx drives the SDR, osmo-bts is the base station, with osmo-bsc / osmo-msc / osmo-hlr forming the core. Together they stand up a full 2G cell on an SDR, the reference open platform for a test/rogue BTS and active IMSI-catcher research. Actively maintained." }, { "slug": "openbts", @@ -51,7 +51,7 @@ "vendor": "SRLabs / Joshua Wright fork", "type": "project", "protocols": ["GSM"], - "note": "GPU/CPU cracker that recovers an A5/1 session key from a captured keystream segment using the ~1.6–2 TB A5/1 rainbow tables (the Berlin A5/1 Security Project). Recovers Kc, which decrypts the rest of a captured call/SMS session. Old but the reference open A5/1 attack; requires the bulky precomputed tables and a known-keystream slice from the capture.", + "note": "GPU/CPU cracker that recovers an A5/1 session key from a captured keystream segment using the ~1.6 to 2 TB A5/1 rainbow tables (the Berlin A5/1 Security Project). Recovers Kc, which decrypts the rest of a captured call/SMS session. Old but the reference open A5/1 attack; requires the bulky precomputed tables and a known-keystream slice from the capture.", "repo": "https://github.com/joswr1ght/kraken" } ] diff --git a/src/data/protocol-tools/lora.json b/src/data/protocol-tools/lora.json index bdfe8e7..cc9f32a 100644 --- a/src/data/protocol-tools/lora.json +++ b/src/data/protocol-tools/lora.json @@ -1,10 +1,10 @@ [ { "slug": "gr-lora_sdr", "name": "gr-lora_sdr", "vendor": "EPFL TCL (Joachim Tapparel)", "type": "software", "protocols": ["LoRa"], "note": "Full GNU Radio software-defined-radio implementation of a LoRa transceiver, including a complete CSS receiver with synchronisation and CFO/STO correction that decodes correctly even at very low SNR. The reference open-source way to de-chirp and demodulate LoRa off an SDR (HackRF / USRP / bladeRF / RTL-SDR).", "repo": "https://github.com/tapparelj/gr-lora_sdr" }, { "slug": "lorattack", "name": "LoRAttack", "vendor": "konicst1", "type": "software", "protocols": ["LoRa"], "note": "LoRaWAN security-assessment toolkit: multi-channel SDR sniffing, session-based capture with automatic handshake storage, session key derivation, Wireshark-compatible PCAP output (LoRaTap DLT), and replay/packet-crafting for vulnerability testing. Built on GNU Radio + USRP; actively under construction.", "repo": "https://github.com/konicst1/lorattack" }, - { "slug": "laf", "name": "LoRaWAN Auditing Framework (LAF)", "vendor": "IOActive", "type": "software", "protocols": ["LoRa"], "note": "Tools to craft, parse, send, analyse and crack LoRaWAN packets to audit or pentest a LoRaWAN infrastructure — MIC recomputation/validation, key-candidate testing and frame forging.", "repo": "https://github.com/IOActive/laf" }, + { "slug": "laf", "name": "LoRaWAN Auditing Framework (LAF)", "vendor": "IOActive", "type": "software", "protocols": ["LoRa"], "note": "Tools to craft, parse, send, analyse and crack LoRaWAN packets to audit or pentest a LoRaWAN infrastructure, MIC recomputation/validation, key-candidate testing and frame forging.", "repo": "https://github.com/IOActive/laf" }, { "slug": "loracrack", "name": "Loracrack", "vendor": "Applied Risk (Sipke Mellema)", "type": "project", "protocols": ["LoRa"], "note": "Proof-of-concept LoRaWAN session cracker that exploits weak or shared Application Keys: given a known/guessable AppKey it derives the session keys from captured packets and validates against the MIC, demonstrating the danger of reused or default AppKeys. Not a brute-forcer of strong AES-128 keys.", "repo": "https://github.com/applied-risk/Loracrack" }, - { "slug": "chirpcat", "name": "ChirpCat", "vendor": "Electronic Cats", "type": "software", "ec": true, "protocols": ["LoRa"], "note": "LoRa/LoRaWAN discovery, classification and capture platform. Listens to LoRaWAN traffic — both uplink and downlink frames — through a gateway backend (Semtech UDP packet forwarder on port 1700), clusters packets by RF characteristics, scores/classifies targets and dispatches follow/capture tasks to CatSniffer workers. Designed to run on the RAK WisGate Connect (Raspberry Pi CM4).", "repo": "https://github.com/ElectronicCats/chirpcat" }, - { "slug": "rak-wisgate-connect", "name": "RAK WisGate Connect", "vendor": "RAKwireless", "type": "hardware", "protocols": ["LoRa", "LoRaWAN"], "spec": "Raspberry Pi CM4 · SX1302/SX1303 concentrator · multi-channel LoRaWAN gateway", "homepage": "https://www.rakwireless.com/en-us/products/wisgate-connect", "software": ["chirpcat"], "note": "RAKwireless multi-channel LoRaWAN gateway built on a Raspberry Pi CM4 with an SX1302/SX1303 concentrator. Receives every LoRaWAN channel at once and feeds frames over the Semtech UDP packet forwarder — the gateway ChirpCat is designed to run on for uplink/downlink capture." }, - { "slug": "chirpstack", "name": "ChirpStack", "vendor": "ChirpStack (Orne Brocaar)", "type": "software", "protocols": ["LoRa", "LoRaWAN"], "homepage": "https://www.chirpstack.io/", "note": "Open-source LoRaWAN Network Server stack (gateway bridge, network server, application server). Provides the network-server side a replay or fuzzing attack is staged against — stand up a ChirpStack instance to model the target's server and observe how it handles replayed, forged or malformed frames.", "repo": "https://github.com/chirpstack/chirpstack" }, - { "slug": "lora-wideband-decoder", "name": "LoRa Wideband Decoder", "vendor": "persistentcache", "type": "software", "protocols": ["LoRa", "LoRaWAN", "Meshtastic"], "repo": "https://github.com/persistentcache/Lora-Wideband-Decoder", "note": "Self-hosted wideband LoRa intercept receiver: streams wideband IQ from a SoapySDR/bladeRF SDR and decodes Meshtastic, LoRaWAN and MeshCore across SF7-SF12 at every standard bandwidth (62.5/125/250/500 kHz) in software, near-real-time, surfacing decoded packets, node identities and a live spectrum waterfall in a local Flask web UI. Captures the whole sub-band at once (~28 Msps on a multi-core host) rather than one channel — validated on bladeRF (native, 28 Msps) and USRP B210/B205mini (SoapyUHD)." } + { "slug": "chirpcat", "name": "ChirpCat", "vendor": "Electronic Cats", "type": "software", "ec": true, "protocols": ["LoRa"], "note": "LoRa/LoRaWAN discovery, classification and capture platform. Listens to LoRaWAN traffic, both uplink and downlink frames, through a gateway backend (Semtech UDP packet forwarder on port 1700), clusters packets by RF characteristics, scores/classifies targets and dispatches follow/capture tasks to CatSniffer workers. Designed to run on the RAK WisGate Connect (Raspberry Pi CM4).", "repo": "https://github.com/ElectronicCats/chirpcat" }, + { "slug": "rak-wisgate-connect", "name": "RAK WisGate Connect", "vendor": "RAKwireless", "type": "hardware", "protocols": ["LoRa", "LoRaWAN"], "spec": "Raspberry Pi CM4 · SX1302/SX1303 concentrator · multi-channel LoRaWAN gateway", "homepage": "https://www.rakwireless.com/en-us/products/wisgate-connect", "software": ["chirpcat"], "note": "RAKwireless multi-channel LoRaWAN gateway built on a Raspberry Pi CM4 with an SX1302/SX1303 concentrator. Receives every LoRaWAN channel at once and feeds frames over the Semtech UDP packet forwarder, the gateway ChirpCat is designed to run on for uplink/downlink capture." }, + { "slug": "chirpstack", "name": "ChirpStack", "vendor": "ChirpStack (Orne Brocaar)", "type": "software", "protocols": ["LoRa", "LoRaWAN"], "homepage": "https://www.chirpstack.io/", "note": "Open-source LoRaWAN Network Server stack (gateway bridge, network server, application server). Provides the network-server side a replay or fuzzing attack is staged against, stand up a ChirpStack instance to model the target's server and observe how it handles replayed, forged or malformed frames.", "repo": "https://github.com/chirpstack/chirpstack" }, + { "slug": "lora-wideband-decoder", "name": "LoRa Wideband Decoder", "vendor": "persistentcache", "type": "software", "protocols": ["LoRa", "LoRaWAN", "Meshtastic"], "repo": "https://github.com/persistentcache/Lora-Wideband-Decoder", "note": "Self-hosted wideband LoRa intercept receiver: streams wideband IQ from a SoapySDR/bladeRF SDR and decodes Meshtastic, LoRaWAN and MeshCore across SF7-SF12 at every standard bandwidth (62.5/125/250/500 kHz) in software, near-real-time, surfacing decoded packets, node identities and a live spectrum waterfall in a local Flask web UI. Captures the whole sub-band at once (~28 Msps on a multi-core host) rather than one channel, validated on bladeRF (native, 28 Msps) and USRP B210/B205mini (SoapyUHD)." } ] diff --git a/src/data/protocol-tools/lte.json b/src/data/protocol-tools/lte.json index ea0e7a7..3b329d2 100644 --- a/src/data/protocol-tools/lte.json +++ b/src/data/protocol-tools/lte.json @@ -1,16 +1,16 @@ [ - { "slug": "srsran-4g", "name": "srsRAN 4G", "vendor": "Software Radio Systems (SRS)", "type": "software", "protocols": ["LTE"], "note": "Open-source SDR 4G suite: srsUE (cell search, MIB/SIB receiver, MAC-LTE/RRC PCAP output), srsENB (a full eNodeB) and srsEPC. The reference open LTE stack on HackRF/bladeRF/USRP — passive receiver for Capture, and the basis for fake-eNB/IMSI-catcher research when transmitting under authorisation.", "repo": "https://github.com/srsran/srsRAN_4G", "homepage": "https://www.srsran.com" }, - { "slug": "srsran-project", "name": "srsRAN Project", "vendor": "Software Radio Systems (SRS)", "type": "software", "protocols": ["LTE"], "note": "SRS's O-RAN 5G CU/DU solution (with 4G support). The newer codebase from the srsRAN team; for LTE cell-search/eNodeB work the srsRAN_4G suite is the directly applicable tool. Note: the srsRAN_Project GitHub repo is archived — check srsran.com for the current distribution.", "repo": "https://github.com/srsran/srsRAN_Project", "homepage": "https://www.srsran.com" }, + { "slug": "srsran-4g", "name": "srsRAN 4G", "vendor": "Software Radio Systems (SRS)", "type": "software", "protocols": ["LTE"], "note": "Open-source SDR 4G suite: srsUE (cell search, MIB/SIB receiver, MAC-LTE/RRC PCAP output), srsENB (a full eNodeB) and srsEPC. The reference open LTE stack on HackRF/bladeRF/USRP, passive receiver for Capture, and the basis for fake-eNB/IMSI-catcher research when transmitting under authorisation.", "repo": "https://github.com/srsran/srsRAN_4G", "homepage": "https://www.srsran.com" }, + { "slug": "srsran-project", "name": "srsRAN Project", "vendor": "Software Radio Systems (SRS)", "type": "software", "protocols": ["LTE"], "note": "SRS's O-RAN 5G CU/DU solution (with 4G support). The newer codebase from the srsRAN team; for LTE cell-search/eNodeB work the srsRAN_4G suite is the directly applicable tool. Note: the srsRAN_Project GitHub repo is archived, check srsran.com for the current distribution.", "repo": "https://github.com/srsran/srsRAN_Project", "homepage": "https://www.srsran.com" }, { "slug": "ltesniffer", "name": "LTESniffer", "vendor": "KAIST SysSec", "type": "software", "protocols": ["LTE"], "note": "Open-source LTE downlink/uplink eavesdropper: decodes PDCCH DCIs and the scheduled PDSCH/PUSCH of a cell, recovering RNTIs and per-UE scheduling information passively. Built for security research on a USRP-class SDR.", "repo": "https://github.com/SysSec-KAIST/LTESniffer" }, - { "slug": "falcon", "name": "FALCON", "vendor": "falkenber9 (TU Dortmund)", "type": "software", "protocols": ["LTE"], "note": "Fast Analysis of LTE Control channels — built on srsRAN to blind-decode the entire PDCCH in real time, exposing every DCI/RNTI scheduling grant in a cell. A passive view of live control-channel activity and resource usage.", "repo": "https://github.com/falkenber9/falcon" }, + { "slug": "falcon", "name": "FALCON", "vendor": "falkenber9 (TU Dortmund)", "type": "software", "protocols": ["LTE"], "note": "Fast Analysis of LTE Control channels, built on srsRAN to blind-decode the entire PDCCH in real time, exposing every DCI/RNTI scheduling grant in a cell. A passive view of live control-channel activity and resource usage.", "repo": "https://github.com/falkenber9/falcon" }, { "slug": "gr-lte", "name": "gr-lte", "vendor": "KIT Communications Engineering Lab", "type": "software", "protocols": ["LTE"], "note": "GNU Radio LTE receiver flowgraph: synchronisation, channel estimation and PBCH decoding implemented as composable DSP blocks. A learning/receiver toolkit for understanding the LTE downlink rather than a full SIB/PDCCH suite (last active ~2020).", "repo": "https://github.com/kit-cel/gr-lte" }, { "slug": "open5gs", "name": "Open5GS", "vendor": "Open5GS", "type": "software", "protocols": ["LTE"], "note": "Open-source C implementation of the EPC (and 5G Core): MME/HSS/SGW/PGW for LTE. Paired with srsENB it provides the core network behind a test/rogue eNodeB so you can provision test subscribers and drive attach/authentication/identity NAS procedures end-to-end.", "repo": "https://github.com/open5gs/open5gs", "homepage": "https://open5gs.org" }, - { "slug": "openairinterface5g", "name": "OpenAirInterface (OAI)", "vendor": "OpenAirInterface Software Alliance", "type": "software", "protocols": ["LTE"], "note": "Full open-source LTE/NR RAN and core reference stack (eNodeB/gNB, UE and EPC). A second independent platform — alongside srsRAN — for standing up a test/rogue eNodeB on a TX-capable SDR and for RRC/NAS signalling experiments and protocol fuzzing in an authorised lab.", "repo": "https://github.com/openairinterface/openairinterface5g", "homepage": "https://openairinterface.org" }, + { "slug": "openairinterface5g", "name": "OpenAirInterface (OAI)", "vendor": "OpenAirInterface Software Alliance", "type": "software", "protocols": ["LTE"], "note": "Full open-source LTE/NR RAN and core reference stack (eNodeB/gNB, UE and EPC). A second independent platform, alongside srsRAN, for standing up a test/rogue eNodeB on a TX-capable SDR and for RRC/NAS signalling experiments and protocol fuzzing in an authorised lab.", "repo": "https://github.com/openairinterface/openairinterface5g", "homepage": "https://openairinterface.org" }, { "slug": "crocodilehunter", "name": "Crocodile Hunter", "vendor": "Electronic Frontier Foundation (EFF)", "type": "software", "protocols": ["LTE"], "note": "EFF's 4G fake-eNodeB / IMSI-catcher detector: passively monitors LTE broadcast (PCI, EARFCN, SIBs) to fingerprint cell-site simulators (Stingray/Hailstorm class) by their anomalies. Built on srsRAN; the defensive counterpart used to validate that a rogue-eNB test is detectable.", "repo": "https://github.com/EFForg/crocodilehunter" }, - { "slug": "imsi-catcher-srsran", "name": "srsRAN active IMSI catcher", "vendor": "roskeys", "type": "software", "protocols": ["LTE"], "note": "A small research project that modifies srsRAN_4G's srsENB into an active IMSI catcher — stands up a fake base station that lures UEs and issues an identity request to extract the IMSI over the unauthenticated pre-AKA NAS exchange. A concrete worked example of the IMSI-catcher attack on srsRAN.", "repo": "https://github.com/roskeys/imsi-catcher" }, + { "slug": "imsi-catcher-srsran", "name": "srsRAN active IMSI catcher", "vendor": "roskeys", "type": "software", "protocols": ["LTE"], "note": "A small research project that modifies srsRAN_4G's srsENB into an active IMSI catcher, stands up a fake base station that lures UEs and issues an identity request to extract the IMSI over the unauthenticated pre-AKA NAS exchange. A concrete worked example of the IMSI-catcher attack on srsRAN.", "repo": "https://github.com/roskeys/imsi-catcher" }, { "slug": "mobileinsight-core", "name": "MobileInsight", "vendor": "MobileInsight (UCLA/Purdue)", "type": "software", "protocols": ["LTE"], "note": "Passive UE-side cellular analyzer: decodes the device's own LTE control-plane messages (RRC, NAS, paging, measurement reports) from a diagnostic feed, so you can observe paging/tracking and measurement behaviour and confirm the effect of an attack from the victim UE's perspective.", "repo": "https://github.com/mobile-insight/mobileinsight-core", "homepage": "http://www.mobileinsight.net" }, - { "slug": "sim7600", "name": "SIMCom SIM7600", "vendor": "SIMCom", "type": "hardware", "protocols": ["LTE"], "spec": "LTE Cat-4 modem · multi-band sub-6 GHz", "homepage": "https://www.simcom.com", "note": "Low-cost commercial SIMCom LTE Cat-4 modem (Qualcomm MDM-based). Reports serving- and neighbour-cell information through its own AT command set — AT+CPSI? returns the system mode, operator (MCC-MNC), LAC, Cell ID, band and EARFCN — a no-SDR way to read which cell a target is on and identify it. Because the baseband is Qualcomm and exposes a /dev/diag port, the same module can also feed QCSuper to capture raw cellular signalling." }, - { "slug": "qcsuper", "name": "QCSuper", "vendor": "P1sec", "type": "software", "protocols": ["LTE", "GSM"], "note": "Captures raw 2G/3G/4G (and, on some modems, 5G) radio frames from Qualcomm-based phones and modems via the /dev/diag DIAG interface, wraps them in GSMTAP and streams a live PCAP into Wireshark. Turns a cheap Qualcomm modem such as the SIM7600 into a passive cellular-signalling sniffer — an alternative to an SDR cell-search receiver.", "repo": "https://github.com/P1sec/QCSuper" }, - { "slug": "orbic-rc400l", "name": "Orbic RC400L hotspot", "vendor": "Orbic", "type": "hardware", "protocols": ["LTE"], "spec": "LTE Cat-4 mobile hotspot · Qualcomm modem (/dev/diag)", "homepage": "https://efforg.github.io/rayhunter/supported-devices.html", "note": "Low-cost (~US$20–30) Qualcomm-based LTE mobile hotspot (also branded Kajeet RC400L) that exposes a /dev/diag diagnostic interface — the reference, best-tested hardware for running EFF's Rayhunter IMSI-catcher detector. The TP-Link M7350 is also supported; in principle any device with a Qualcomm modem exposing /dev/diag may work." }, - { "slug": "rayhunter", "name": "Rayhunter", "vendor": "Electronic Frontier Foundation (EFF)", "type": "software", "protocols": ["LTE"], "note": "EFF's IMSI-catcher / cell-site-simulator detector. Runs as firmware on a cheap Qualcomm-based mobile hotspot (Orbic RC400L, TP-Link M7350) and passively analyses the LTE control plane from the modem's /dev/diag feed, raising an alert on cell-site-simulator behaviour — unexpected identity/IMSI requests, downgrade attempts or suspicious tower configuration. The portable, low-cost blue-team counterpart to Crocodile Hunter for confirming whether a rogue station is present, with no SDR or host PC.", "repo": "https://github.com/EFForg/rayhunter", "homepage": "https://efforg.github.io/rayhunter/" } + { "slug": "sim7600", "name": "SIMCom SIM7600", "vendor": "SIMCom", "type": "hardware", "protocols": ["LTE"], "spec": "LTE Cat-4 modem · multi-band sub-6 GHz", "homepage": "https://www.simcom.com", "note": "Low-cost commercial SIMCom LTE Cat-4 modem (Qualcomm MDM-based). Reports serving- and neighbour-cell information through its own AT command set, AT+CPSI? returns the system mode, operator (MCC-MNC), LAC, Cell ID, band and EARFCN, a no-SDR way to read which cell a target is on and identify it. Because the baseband is Qualcomm and exposes a /dev/diag port, the same module can also feed QCSuper to capture raw cellular signalling." }, + { "slug": "qcsuper", "name": "QCSuper", "vendor": "P1sec", "type": "software", "protocols": ["LTE", "GSM"], "note": "Captures raw 2G/3G/4G (and, on some modems, 5G) radio frames from Qualcomm-based phones and modems via the /dev/diag DIAG interface, wraps them in GSMTAP and streams a live PCAP into Wireshark. Turns a cheap Qualcomm modem such as the SIM7600 into a passive cellular-signalling sniffer, an alternative to an SDR cell-search receiver.", "repo": "https://github.com/P1sec/QCSuper" }, + { "slug": "orbic-rc400l", "name": "Orbic RC400L hotspot", "vendor": "Orbic", "type": "hardware", "protocols": ["LTE"], "spec": "LTE Cat-4 mobile hotspot · Qualcomm modem (/dev/diag)", "homepage": "https://efforg.github.io/rayhunter/supported-devices.html", "note": "Low-cost (~US$20 to 30) Qualcomm-based LTE mobile hotspot (also branded Kajeet RC400L) that exposes a /dev/diag diagnostic interface, the reference, best-tested hardware for running EFF's Rayhunter IMSI-catcher detector. The TP-Link M7350 is also supported; in principle any device with a Qualcomm modem exposing /dev/diag may work." }, + { "slug": "rayhunter", "name": "Rayhunter", "vendor": "Electronic Frontier Foundation (EFF)", "type": "software", "protocols": ["LTE"], "note": "EFF's IMSI-catcher / cell-site-simulator detector. Runs as firmware on a cheap Qualcomm-based mobile hotspot (Orbic RC400L, TP-Link M7350) and passively analyses the LTE control plane from the modem's /dev/diag feed, raising an alert on cell-site-simulator behaviour, unexpected identity/IMSI requests, downgrade attempts or suspicious tower configuration. The portable, low-cost blue-team counterpart to Crocodile Hunter for confirming whether a rogue station is present, with no SDR or host PC.", "repo": "https://github.com/EFForg/rayhunter", "homepage": "https://efforg.github.io/rayhunter/" } ] diff --git a/src/data/protocol-tools/nr5g.json b/src/data/protocol-tools/nr5g.json index 71cdd0d..46d2278 100644 --- a/src/data/protocol-tools/nr5g.json +++ b/src/data/protocol-tools/nr5g.json @@ -1,8 +1,8 @@ [ - { "slug": "free5gc", "name": "free5GC", "vendor": "free5GC (NYCU/Taiwan)", "type": "software", "protocols": ["5G NR"], "spec": "3GPP R15 5G Core · AMF/SMF/UPF/AUSF/UDM", "note": "Open-source 3GPP Release-15 5G Core network in Go — AMF, SMF, UPF, AUSF, UDM, NRF and the rest of the SBA. An alternative to Open5GS as the 5GC behind a test gNB (srsRAN/OAI): provision test subscribers, drive 5G-AKA authentication and the NAS-5GS registration procedures, and exercise NGAP between your gNB and core. Standalone (SA) only.", "repo": "https://github.com/free5gc/free5gc", "homepage": "https://free5gc.org" }, - { "slug": "5greplay", "name": "5Greplay", "vendor": "Montimage", "type": "software", "protocols": ["5G NR"], "note": "5G network-traffic fuzzer and replay engine (built on Montimage's MMT). Takes captured 5G control-/data-plane traffic, lets you write rules to modify fields, and replays the altered packets — online or offline — toward a target 5G component (AMF/SMF over NGAP/SCTP, or a gNB) for protocol fuzzing and attack-injection testing. Operates on traffic, not radio: it consumes a capture (e.g. from Wireshark) and a target core, no SDR.", "repo": "https://github.com/Montimage/5Greplay", "homepage": "https://5greplay.org" }, - { "slug": "5gsniffer", "name": "5GSniffer", "vendor": "Sprite Lab (Northeastern University)", "type": "software", "protocols": ["5G NR"], "note": "Open-source 5G NR Physical Downlink Control Channel (PDCCH) blind decoder: passively recovers the Downlink Control Information (DCI) and the RNTIs active in a cell, exposing scheduling/identity activity for traffic analysis. Written in C++ on srsRAN libraries; FDD, FR1 sub-6 GHz. Research-grade — the current release recommends working from a recorded I/Q file rather than live SDR, and live capture needs extra setup.", "repo": "https://github.com/spritelab/5GSniffer" }, - { "slug": "sni5gect", "name": "Sni5Gect", "vendor": "ASSET Research Group (SUTD)", "type": "software", "protocols": ["5G NR"], "spec": "USRP B210/X310 · Ubuntu 22.04 · 12-core/16 GB host", "note": "Open-source 5G NR sniffer and downlink injector framework built on srsRAN. Passively captures unencrypted MAC-NR messages between a gNB and a UE (with Wireshark support) and can inject crafted MAC-NR packets to a target at specific post-connection states (registration/authentication/RRC) — used for modem crashes, downgrades, fingerprinting and auth-bypass research without a rogue base station. Heavy host requirements; FR1 sub-6 GHz on a USRP.", "repo": "https://github.com/asset-group/Sni5Gect-5GNR-sniffing-and-exploitation", "homepage": "https://sni5gect.com" }, + { "slug": "free5gc", "name": "free5GC", "vendor": "free5GC (NYCU/Taiwan)", "type": "software", "protocols": ["5G NR"], "spec": "3GPP R15 5G Core · AMF/SMF/UPF/AUSF/UDM", "note": "Open-source 3GPP Release-15 5G Core network in Go, AMF, SMF, UPF, AUSF, UDM, NRF and the rest of the SBA. An alternative to Open5GS as the 5GC behind a test gNB (srsRAN/OAI): provision test subscribers, drive 5G-AKA authentication and the NAS-5GS registration procedures, and exercise NGAP between your gNB and core. Standalone (SA) only.", "repo": "https://github.com/free5gc/free5gc", "homepage": "https://free5gc.org" }, + { "slug": "5greplay", "name": "5Greplay", "vendor": "Montimage", "type": "software", "protocols": ["5G NR"], "note": "5G network-traffic fuzzer and replay engine (built on Montimage's MMT). Takes captured 5G control-/data-plane traffic, lets you write rules to modify fields, and replays the altered packets, online or offline, toward a target 5G component (AMF/SMF over NGAP/SCTP, or a gNB) for protocol fuzzing and attack-injection testing. Operates on traffic, not radio: it consumes a capture (e.g. from Wireshark) and a target core, no SDR.", "repo": "https://github.com/Montimage/5Greplay", "homepage": "https://5greplay.org" }, + { "slug": "5gsniffer", "name": "5GSniffer", "vendor": "Sprite Lab (Northeastern University)", "type": "software", "protocols": ["5G NR"], "note": "Open-source 5G NR Physical Downlink Control Channel (PDCCH) blind decoder: passively recovers the Downlink Control Information (DCI) and the RNTIs active in a cell, exposing scheduling/identity activity for traffic analysis. Written in C++ on srsRAN libraries; FDD, FR1 sub-6 GHz. Research-grade, the current release recommends working from a recorded I/Q file rather than live SDR, and live capture needs extra setup.", "repo": "https://github.com/spritelab/5GSniffer" }, + { "slug": "sni5gect", "name": "Sni5Gect", "vendor": "ASSET Research Group (SUTD)", "type": "software", "protocols": ["5G NR"], "spec": "USRP B210/X310 · Ubuntu 22.04 · 12-core/16 GB host", "note": "Open-source 5G NR sniffer and downlink injector framework built on srsRAN. Passively captures unencrypted MAC-NR messages between a gNB and a UE (with Wireshark support) and can inject crafted MAC-NR packets to a target at specific post-connection states (registration/authentication/RRC), used for modem crashes, downgrades, fingerprinting and auth-bypass research without a rogue base station. Heavy host requirements; FR1 sub-6 GHz on a USRP.", "repo": "https://github.com/asset-group/Sni5Gect-5GNR-sniffing-and-exploitation", "homepage": "https://sni5gect.com" }, { "slug": "5ghoul", "name": "5Ghoul", "vendor": "ASSET Research Group (SUTD)", "type": "software", "protocols": ["5G NR"], "note": "5G NR attack and fuzzing suite that disrupts COTS smartphones (Qualcomm, MediaTek basebands) from a malicious gNB: a set of pre-authentication RRC/NAS vulnerabilities plus a 5G fuzzer, run on top of an OpenAirInterface gNB. For authorised, RF-contained testing of a UE's resilience to a hostile base station.", "repo": "https://github.com/asset-group/5ghoul-5g-nr-attacks", "homepage": "https://5ghoul.com" }, - { "slug": "quectel-rm500q", "name": "Quectel RM500Q-GL", "vendor": "Quectel", "type": "hardware", "protocols": ["5G NR"], "spec": "5G NR Sub-6 (FR1) module · Qualcomm Snapdragon X55 (SDX55) · NSA/SA", "homepage": "https://www.quectel.com/product/5g-rm500q-gl/", "software": ["qcsuper"], "note": "Commercial 5G NR Sub-6 (FR1) modem module built on the Qualcomm Snapdragon X55 (SDX55). Being Qualcomm-based it exposes a DIAG interface, so QCSuper can pull raw 5G/LTE signalling off it into Wireshark — a no-SDR route to 5G control-plane frames (5G frame coverage is modem/firmware-dependent)." } + { "slug": "quectel-rm500q", "name": "Quectel RM500Q-GL", "vendor": "Quectel", "type": "hardware", "protocols": ["5G NR"], "spec": "5G NR Sub-6 (FR1) module · Qualcomm Snapdragon X55 (SDX55) · NSA/SA", "homepage": "https://www.quectel.com/product/5g-rm500q-gl/", "software": ["qcsuper"], "note": "Commercial 5G NR Sub-6 (FR1) modem module built on the Qualcomm Snapdragon X55 (SDX55). Being Qualcomm-based it exposes a DIAG interface, so QCSuper can pull raw 5G/LTE signalling off it into Wireshark, a no-SDR route to 5G control-plane frames (5G frame coverage is modem/firmware-dependent)." } ] diff --git a/src/data/protocol-tools/rfid.json b/src/data/protocol-tools/rfid.json index fef51d1..3ab5893 100644 --- a/src/data/protocol-tools/rfid.json +++ b/src/data/protocol-tools/rfid.json @@ -1,9 +1,9 @@ [ - { "slug": "acr122u", "name": "PN532 / ACR122U USB NFC reader", "vendor": "generic (NXP PN532 / ACS)", "type": "hardware", "protocols": ["NFC", "RFID"], "note": "Cheap USB 13.56 MHz HF reader (ACR122U / PN532 breakout) — the standard libnfc target for reading and dumping ISO 14443-A MIFARE cards and for running the mfoc/mfcuk crackers. HF only; no LF, and weaker than a Proxmark for adversarial work.", "homepage": "https://github.com/nfc-tools/libnfc/wiki" }, - { "slug": "libnfc", "name": "libnfc", "vendor": "nfc-tools", "type": "software", "protocols": ["NFC", "RFID"], "note": "Platform-independent NFC library and tools (nfc-list, nfc-mfclassic) that drive PN532/ACR122U-class HF readers to read and dump ISO 14443-A MIFARE cards — and the host stack the mfoc and mfcuk Crypto1 crackers build on.", "repo": "https://github.com/nfc-tools/libnfc" }, + { "slug": "acr122u", "name": "PN532 / ACR122U USB NFC reader", "vendor": "generic (NXP PN532 / ACS)", "type": "hardware", "protocols": ["NFC", "RFID"], "note": "Cheap USB 13.56 MHz HF reader (ACR122U / PN532 breakout), the standard libnfc target for reading and dumping ISO 14443-A MIFARE cards and for running the mfoc/mfcuk crackers. HF only; no LF, and weaker than a Proxmark for adversarial work.", "homepage": "https://github.com/nfc-tools/libnfc/wiki" }, + { "slug": "libnfc", "name": "libnfc", "vendor": "nfc-tools", "type": "software", "protocols": ["NFC", "RFID"], "note": "Platform-independent NFC library and tools (nfc-list, nfc-mfclassic) that drive PN532/ACR122U-class HF readers to read and dump ISO 14443-A MIFARE cards, and the host stack the mfoc and mfcuk Crypto1 crackers build on.", "repo": "https://github.com/nfc-tools/libnfc" }, { "slug": "mfoc", "name": "mfoc", "vendor": "nfc-tools", "type": "software", "protocols": ["NFC", "RFID"], "note": "MIFARE Classic Offline Cracker: given at least one known sector key it runs the nested attack to recover all remaining Crypto1 keys and dump the card, over a libnfc-driven PN532 reader. Default/transport keys are tried automatically.", "repo": "https://github.com/nfc-tools/mfoc" }, - { "slug": "mfcuk", "name": "MFCUK", "vendor": "nfc-tools", "type": "software", "protocols": ["NFC", "RFID"], "note": "MiFare Classic Universal toolKit implementing the darkside attack to recover a first Crypto1 key when no default key works — the bootstrap that lets mfoc finish the rest. Runs on a libnfc PN532/ACR122U reader.", "repo": "https://github.com/nfc-tools/mfcuk" }, - { "slug": "mfdread", "name": "mfdread", "vendor": "Anton Shipulin (zhovner)", "type": "software", "protocols": ["NFC", "RFID"], "note": "Parses MIFARE Classic 1k/4k dumps into human-readable form — per-sector data, keys A/B and access-condition bits — so a recovered dump becomes readable application data.", "repo": "https://github.com/zhovner/mfdread" }, - { "slug": "pm3-client", "name": "Proxmark3 client (pm3)", "vendor": "RFID Research Group (Iceman fork)", "type": "software", "protocols": ["NFC", "RFID"], "note": "The host client that drives the Proxmark3 over USB — the `pm3` shell from the RfidResearchGroup/proxmark3 (Iceman) repo. Runs every Proxmark workflow from the laptop: `lf/hf search` to fingerprint a tag, read/dump LF IDs and HF cards, the full Crypto1 suite (`hf mf darkside`/`nested`/`hardnested`/`mfkey`), clone/simulate, and `hf 14a` sniff plus the `hf_reblay` standalone mode for an ISO 14443-A relay/MITM. The firmware and client ship together; this is the software you actually type into.", "repo": "https://github.com/RfidResearchGroup/proxmark3" }, + { "slug": "mfcuk", "name": "MFCUK", "vendor": "nfc-tools", "type": "software", "protocols": ["NFC", "RFID"], "note": "MiFare Classic Universal toolKit implementing the darkside attack to recover a first Crypto1 key when no default key works, the bootstrap that lets mfoc finish the rest. Runs on a libnfc PN532/ACR122U reader.", "repo": "https://github.com/nfc-tools/mfcuk" }, + { "slug": "mfdread", "name": "mfdread", "vendor": "Anton Shipulin (zhovner)", "type": "software", "protocols": ["NFC", "RFID"], "note": "Parses MIFARE Classic 1k/4k dumps into human-readable form, per-sector data, keys A/B and access-condition bits, so a recovered dump becomes readable application data.", "repo": "https://github.com/zhovner/mfdread" }, + { "slug": "pm3-client", "name": "Proxmark3 client (pm3)", "vendor": "RFID Research Group (Iceman fork)", "type": "software", "protocols": ["NFC", "RFID"], "note": "The host client that drives the Proxmark3 over USB, the `pm3` shell from the RfidResearchGroup/proxmark3 (Iceman) repo. Runs every Proxmark workflow from the laptop: `lf/hf search` to fingerprint a tag, read/dump LF IDs and HF cards, the full Crypto1 suite (`hf mf darkside`/`nested`/`hardnested`/`mfkey`), clone/simulate, and `hf 14a` sniff plus the `hf_reblay` standalone mode for an ISO 14443-A relay/MITM. The firmware and client ship together; this is the software you actually type into.", "repo": "https://github.com/RfidResearchGroup/proxmark3" }, { "slug": "chameleon-ultra-gui", "name": "Chameleon Ultra GUI", "vendor": "GameTec-live", "type": "software", "protocols": ["NFC", "RFID"], "note": "Cross-platform Flutter app (Windows, Linux, macOS, Android, iOS/iPadOS) that drives the ChameleonUltra/Lite: read HF/LF cards, manage and write emulation slots, save card data, run the MIFARE Classic dictionary/recovery flow and emulate stored credentials. The host front-end for the otherwise headless Chameleon.", "repo": "https://github.com/GameTec-live/ChameleonUltraGUI" } ] diff --git a/src/data/protocol-tools/subg.json b/src/data/protocol-tools/subg.json index 4e3ad40..93e9001 100644 --- a/src/data/protocol-tools/subg.json +++ b/src/data/protocol-tools/subg.json @@ -6,7 +6,7 @@ "type": "software", "protocols": ["Sub-GHz"], "repo": "https://github.com/merbanan/rtl_433", - "note": "Generic ISM-band receiver and decoder for 315 / 433.92 / 868 / 915 MHz devices. Out of the box it recognises 320+ device protocols — weather and soil/temperature sensors, TPMS tyre-pressure monitors, energy/water meters, doorbells, contact sensors and many remotes — and demodulates both OOK/ASK and FSK, printing each decoded device as a line of JSON (also CSV, MQTT, InfluxDB, syslog). It is itself the decoder: where Wi-Fi or BLE hand a PCAP to Wireshark, rtl_433 turns raw I/Q straight into named, fielded device events. Runs on RTL-SDR natively and on HackRF / other radios via SoapySDR." + "note": "Generic ISM-band receiver and decoder for 315 / 433.92 / 868 / 915 MHz devices. Out of the box it recognises 320+ device protocols, weather and soil/temperature sensors, TPMS tyre-pressure monitors, energy/water meters, doorbells, contact sensors and many remotes, and demodulates both OOK/ASK and FSK, printing each decoded device as a line of JSON (also CSV, MQTT, InfluxDB, syslog). It is itself the decoder: where Wi-Fi or BLE hand a PCAP to Wireshark, rtl_433 turns raw I/Q straight into named, fielded device events. Runs on RTL-SDR natively and on HackRF / other radios via SoapySDR." }, { "slug": "flipper-zero", @@ -14,10 +14,10 @@ "vendor": "Flipper Devices", "type": "hardware", "protocols": ["Sub-GHz", "RFID", "NFC", "Infrared"], - "spec": "CC1101 transceiver · RX/TX 300–348, 387–464 & 779–928 MHz · OOK/ASK + (G)FSK · handheld", + "spec": "CC1101 transceiver · RX/TX 300 to 348, 387 to 464 & 779 to 928 MHz · OOK/ASK + (G)FSK · handheld", "homepage": "https://flipper.net/", "software": ["flipperzero-firmware"], - "note": "Handheld multitool whose built-in CC1101 transceiver receives and transmits across the 300–348, 387–464 and 779–928 MHz sub-GHz bands — the everyday field radio for reading, saving and replaying garage/gate/doorbell remotes and other fixed-code devices, with no laptop or SDR. OOK/ASK and (G)FSK; its Read mode decodes known protocols and Read RAW captures unknown ones for later replay." + "note": "Handheld multitool whose built-in CC1101 transceiver receives and transmits across the 300 to 348, 387 to 464 and 779 to 928 MHz sub-GHz bands, the everyday field radio for reading, saving and replaying garage/gate/doorbell remotes and other fixed-code devices, with no laptop or SDR. OOK/ASK and (G)FSK; its Read mode decodes known protocols and Read RAW captures unknown ones for later replay." }, { "slug": "flipperzero-firmware", @@ -26,6 +26,6 @@ "type": "software", "protocols": ["Sub-GHz"], "repo": "https://github.com/flipperdevices/flipperzero-firmware", - "note": "The open-source firmware that runs the Flipper Zero's Sub-GHz app: Read (decode a known protocol), Read RAW (capture an unknown signal as raw timings), Save and Send (replay/emulate a saved signal), and a manual virtual-remote builder. The official firmware deliberately refuses to save or replay rolling-code signals (e.g. KeeLoq) as a built-in safety limit — capture-and-replay works on fixed-code devices, not rolling-code ones, on stock firmware." + "note": "The open-source firmware that runs the Flipper Zero's Sub-GHz app: Read (decode a known protocol), Read RAW (capture an unknown signal as raw timings), Save and Send (replay/emulate a saved signal), and a manual virtual-remote builder. The official firmware deliberately refuses to save or replay rolling-code signals (e.g. KeeLoq) as a built-in safety limit, capture-and-replay works on fixed-code devices, not rolling-code ones, on stock firmware." } ] diff --git a/src/data/protocol-tools/thread.json b/src/data/protocol-tools/thread.json index f9a7a14..f084a05 100644 --- a/src/data/protocol-tools/thread.json +++ b/src/data/protocol-tools/thread.json @@ -33,7 +33,7 @@ "type": "project", "protocols": ["Thread", "Wi-Fi", "BLE"], "repo": "https://github.com/project-chip/connectedhomeip", - "note": "The official open-source Matter (formerly Project CHIP) SDK from the Connectivity Standards Alliance. Provides the device stack, example apps and the chip-tool controller — the reference codebase for building and exercising Matter-over-Thread and Matter-over-Wi-Fi nodes and their commissioning." + "note": "The official open-source Matter (formerly Project CHIP) SDK from the Connectivity Standards Alliance. Provides the device stack, example apps and the chip-tool controller, the reference codebase for building and exercising Matter-over-Thread and Matter-over-Wi-Fi nodes and their commissioning." }, { "slug": "chip-tool", @@ -42,7 +42,7 @@ "type": "software", "protocols": ["Thread", "Wi-Fi", "BLE"], "repo": "https://github.com/project-chip/connectedhomeip", - "note": "The Matter controller/commissioner CLI from the connectedhomeip SDK (examples/chip-tool). Commissions a Matter device over Bluetooth LE — establishing a PASE (SPAKE2+) session from the setup passcode, handing over Thread/Wi-Fi credentials with `pairing ble-thread` / `pairing ble-wifi` (or `pairing onnetwork` / `pairing code` once on-network) — then drives it with CASE-secured operational commands. Also opens a second commissioning window (`pairing open-commissioning-window`) to test multi-admin. The tool for assessing Matter onboarding and the application-layer cluster interface." + "note": "The Matter controller/commissioner CLI from the connectedhomeip SDK (examples/chip-tool). Commissions a Matter device over Bluetooth LE, establishing a PASE (SPAKE2+) session from the setup passcode, handing over Thread/Wi-Fi credentials with `pairing ble-thread` / `pairing ble-wifi` (or `pairing onnetwork` / `pairing code` once on-network), then drives it with CASE-secured operational commands. Also opens a second commissioning window (`pairing open-commissioning-window`) to test multi-admin. The tool for assessing Matter onboarding and the application-layer cluster interface." }, { "slug": "chip-repl", @@ -51,7 +51,7 @@ "type": "software", "protocols": ["Thread", "Wi-Fi", "BLE"], "repo": "https://github.com/project-chip/connectedhomeip", - "note": "The Python Matter controller and interactive REPL from the connectedhomeip SDK (src/controller/python, matter-repl.py). Same native CHIP device-controller stack as chip-tool but scriptable: stand up a fabric, commission over BLE, then read/subscribe/write attributes and invoke cluster commands from Python — convenient for automating commissioning-attack and cluster-enumeration workflows and for multi-fabric tests." + "note": "The Python Matter controller and interactive REPL from the connectedhomeip SDK (src/controller/python, matter-repl.py). Same native CHIP device-controller stack as chip-tool but scriptable: stand up a fabric, commission over BLE, then read/subscribe/write attributes and invoke cluster commands from Python, convenient for automating commissioning-attack and cluster-enumeration workflows and for multi-fabric tests." }, { "slug": "python-matter-server", @@ -60,7 +60,7 @@ "type": "software", "protocols": ["Thread", "Wi-Fi", "BLE"], "repo": "https://github.com/matter-js/python-matter-server", - "note": "A CSA-certified Matter Controller Server (the one behind Home Assistant's Matter integration) that wraps the CHIP SDK and exposes commissioning and the operational cluster model over a WebSocket API. Acts as a standing controller/commissioner you can drive programmatically — commission a node over BLE, then enumerate and exercise its clusters. Maintenance mode (being rebuilt on matter.js), but a real, working Matter controller." + "note": "A CSA-certified Matter Controller Server (the one behind Home Assistant's Matter integration) that wraps the CHIP SDK and exposes commissioning and the operational cluster model over a WebSocket API. Acts as a standing controller/commissioner you can drive programmatically, commission a node over BLE, then enumerate and exercise its clusters. Maintenance mode (being rebuilt on matter.js), but a real, working Matter controller." }, { "slug": "matter-dcl", @@ -70,6 +70,6 @@ "protocols": ["Thread", "Wi-Fi", "BLE"], "repo": "https://github.com/zigbee-alliance/distributed-compliance-ledger", "homepage": "https://webui.dcl.csa-iot.org/", - "note": "The CSA-run public ledger (Cosmos SDK / CometBFT) of Matter device data: vendor and product info keyed by Vendor ID (VID) and Product ID (PID), certification status, and the Product Attestation Authority (PAA) root certificates that commissioners trust for device attestation. At Identify, the DCL turns the VID/PID read off a device's onboarding payload into a known vendor/product and certification record — and a Test-Vendor VID (0xFFF1–0xFFF4) on a 'production' device is an immediate red flag." + "note": "The CSA-run public ledger (Cosmos SDK / CometBFT) of Matter device data: vendor and product info keyed by Vendor ID (VID) and Product ID (PID), certification status, and the Product Attestation Authority (PAA) root certificates that commissioners trust for device attestation. At Identify, the DCL turns the VID/PID read off a device's onboarding payload into a known vendor/product and certification record, and a Test-Vendor VID (0xFFF1 to 0xFFF4) on a 'production' device is an immediate red flag." } ] diff --git a/src/data/protocol-tools/uwb.json b/src/data/protocol-tools/uwb.json index ca51929..2e1dad9 100644 --- a/src/data/protocol-tools/uwb.json +++ b/src/data/protocol-tools/uwb.json @@ -8,7 +8,7 @@ "homepage": "https://www.qorvo.com/products/p/DWM3000EVB", "spec": "Arduino-shield eval board · DWM3000 module (DW3110 transceiver) · IEEE 802.15.4z BPRF · UWB ch 5 (6.5 GHz) / ch 9 (8 GHz) · FiRa PHY/MAC, Apple U1/U2 interop", "software": ["seemoo-uwb-sniffer", "dwm3000-dwt-driver"], - "note": "The reference DW3000-family UWB development shield: a DWM3000 module (DW3110 second-generation impulse-radio transceiver) on an Arduino form factor. Designed against the FiRa PHY/MAC and interoperable with Apple's U1 & U2 chips, on channels 5 (6.5 GHz) and 9 (8 GHz). Drive it from a host MCU (e.g. a NUCLEO-F429ZI or nRF52840) to range, log or — with the SEEMOO sniffer firmware — capture 802.15.4z frames. The same board (a ~$65 EVB + nRF52DK) was the attack platform in the Ghost Peak research." + "note": "The reference DW3000-family UWB development shield: a DWM3000 module (DW3110 second-generation impulse-radio transceiver) on an Arduino form factor. Designed against the FiRa PHY/MAC and interoperable with Apple's U1 & U2 chips, on channels 5 (6.5 GHz) and 9 (8 GHz). Drive it from a host MCU (e.g. a NUCLEO-F429ZI or nRF52840) to range, log or, with the SEEMOO sniffer firmware, capture 802.15.4z frames. The same board (a ~$65 EVB + nRF52DK) was the attack platform in the Ghost Peak research." }, { "slug": "makerfabs-esp32-uwb-dw3000", @@ -19,7 +19,7 @@ "repo": "https://github.com/Makerfabs/Makerfabs-ESP32-UWB-DW3000", "spec": "ESP32 + Qorvo DW3000 (DW3110) · IEEE 802.15.4z BPRF · UWB ch 5 / ch 9 · Arduino/ESP-IDF", "software": ["dwm3000-dwt-driver"], - "note": "Low-cost open hobbyist board pairing an ESP32 with a Qorvo DW3000 (DW3110) UWB transceiver — the accessible way to bring up two-way ranging and tag/anchor positioning experiments in the Arduino/ESP-IDF ecosystem. Open example firmware and an Arduino DW3000 library ship in the Makerfabs GitHub repo. A development/ranging board, not a turnkey sniffer; use it to learn the radio, characterise a scheme's parameters, or build a controllable peer for authorised testing." + "note": "Low-cost open hobbyist board pairing an ESP32 with a Qorvo DW3000 (DW3110) UWB transceiver, the accessible way to bring up two-way ranging and tag/anchor positioning experiments in the Arduino/ESP-IDF ecosystem. Open example firmware and an Arduino DW3000 library ship in the Makerfabs GitHub repo. A development/ranging board, not a turnkey sniffer; use it to learn the radio, characterise a scheme's parameters, or build a controllable peer for authorised testing." }, { "slug": "mdek1001", @@ -29,7 +29,7 @@ "protocols": ["UWB"], "homepage": "https://www.qorvo.com/products/p/MDEK1001", "spec": "12 × DWM1001-DEV boards (DW1000 transceiver) · nRF52832 host · RTLS anchor/tag/bridge · IEEE 802.15.4-2011 UWB", - "note": "The classic first-generation Decawave/Qorvo RTLS development kit: twelve enclosed DWM1001-DEV boards (each a DW1000 UWB transceiver plus an nRF52832 host), configurable as anchors, tags or bridge nodes to stand up a real-time location system out of the box. DW1000 is the older generation — it predates the 802.15.4z STS security enhancements that the DW3000 family adds — so it is ideal for learning UWB ranging mechanics, less so for assessing modern secure-ranging schemes. Note: end-of-life as of Dec 2025 (last orders mid-2026); Qorvo points new designs at the QM33-series kits." + "note": "The classic first-generation Decawave/Qorvo RTLS development kit: twelve enclosed DWM1001-DEV boards (each a DW1000 UWB transceiver plus an nRF52832 host), configurable as anchors, tags or bridge nodes to stand up a real-time location system out of the box. DW1000 is the older generation, it predates the 802.15.4z STS security enhancements that the DW3000 family adds, so it is ideal for learning UWB ranging mechanics, less so for assessing modern secure-ranging schemes. Note: end-of-life as of Dec 2025 (last orders mid-2026); Qorvo points new designs at the QM33-series kits." }, { "slug": "murata-type2bp", @@ -38,8 +38,8 @@ "type": "hardware", "protocols": ["UWB"], "homepage": "https://www.murata.com/products/connectivitymodule/ultra-wide-band/nxp/type2bp", - "spec": "NXP Trimension SR150 chipset · FiRa Certified · UWB ch 5 / ch 9 (6.25–8.25 GHz) · two-way ranging + 2D/3D Angle-of-Arrival (up to 3 antennas) · SPI", - "note": "A compact production UWB module built on NXP's Trimension SR150 (not a DW3000) — included here because the NXP UWB silicon family is the other half of the deployed ecosystem (NXP chips feature in car digital-key and phone designs, and inter-operate with Apple U1 in the Ghost Peak results). FiRa Certified, supports two-way ranging and 2D/3D Angle-of-Arrival with up to three antennas. A module for building/representing an NXP-based ranging peer; identify it by its SR150 silicon rather than assuming every UWB target is a Qorvo DW3000." + "spec": "NXP Trimension SR150 chipset · FiRa Certified · UWB ch 5 / ch 9 (6.25 to 8.25 GHz) · two-way ranging + 2D/3D Angle-of-Arrival (up to 3 antennas) · SPI", + "note": "A compact production UWB module built on NXP's Trimension SR150 (not a DW3000), included here because the NXP UWB silicon family is the other half of the deployed ecosystem (NXP chips feature in car digital-key and phone designs, and inter-operate with Apple U1 in the Ghost Peak results). FiRa Certified, supports two-way ranging and 2D/3D Angle-of-Arrival with up to three antennas. A module for building/representing an NXP-based ranging peer; identify it by its SR150 silicon rather than assuming every UWB target is a Qorvo DW3000." }, { "slug": "seemoo-uwb-sniffer", @@ -48,7 +48,7 @@ "type": "software", "protocols": ["UWB"], "repo": "https://github.com/seemoo-lab/uwb-sniffer", - "note": "The reference OPEN UWB sniffer: firmware for a Qorvo DWM3000EVB driven by a host (a NUCLEO-F429ZI in the reference build; an nRF52840 with code changes) that captures IEEE 802.15.4z UWB frames and forwards them to Wireshark over a sensniff named pipe, with timestamps at the DW3000's 15.65 ps accuracy. Comes out of the SEEMOO/ETH Ghost Peak line of research. Honest limits: UWB has many PHY parameters (channel, preamble code, data rate, STS mode and length) that must be known IN ADVANCE to lock onto a link, and it forwards malformed frames too — so it is a research instrument, not a push-button capture. It does NOT break the STS or recover keys; it captures the over-the-air frames you can already decode." + "note": "The reference OPEN UWB sniffer: firmware for a Qorvo DWM3000EVB driven by a host (a NUCLEO-F429ZI in the reference build; an nRF52840 with code changes) that captures IEEE 802.15.4z UWB frames and forwards them to Wireshark over a sensniff named pipe, with timestamps at the DW3000's 15.65 ps accuracy. Comes out of the SEEMOO/ETH Ghost Peak line of research. Honest limits: UWB has many PHY parameters (channel, preamble code, data rate, STS mode and length) that must be known IN ADVANCE to lock onto a link, and it forwards malformed frames too, so it is a research instrument, not a push-button capture. It does NOT break the STS or recover keys; it captures the over-the-air frames you can already decode." }, { "slug": "dwm3000-dwt-driver", @@ -57,7 +57,7 @@ "type": "project", "protocols": ["UWB"], "repo": "https://github.com/foldedtoad/dwm3000", - "note": "An open port of Qorvo/Decawave's DWM3000 driver and ranging examples (the dwt_uwb_driver API) to the DWS3000 Arduino shield, runnable under Zephyr. The practical glue for bringing up a DW3000 board, configuring its 802.15.4z PHY parameters (channel, preamble, PRF, STS mode), and running two-way-ranging exchanges you can log — the dev-board path for capturing/characterising ranging behaviour. A development driver, not an attack tool." + "note": "An open port of Qorvo/Decawave's DWM3000 driver and ranging examples (the dwt_uwb_driver API) to the DWS3000 Arduino shield, runnable under Zephyr. The practical glue for bringing up a DW3000 board, configuring its 802.15.4z PHY parameters (channel, preamble, PRF, STS mode), and running two-way-ranging exchanges you can log, the dev-board path for capturing/characterising ranging behaviour. A development driver, not an attack tool." }, { "slug": "forthink-uwb-sniffer", @@ -66,7 +66,7 @@ "type": "software", "protocols": ["UWB"], "repo": "https://github.com/forthink-xyz/forthink_uwb_sniffer_tool", - "note": "Open-source host software and a Wireshark plugin (forthink-xyz/uwb-sniffer-wireshark) that monitor and decode CCC, FiRa and IEEE 802.15.4a/z UWB — including parameters for Apple Car-Key and AirTag/Nearby-Interaction (FiRa) traffic. Caveat: the software is open but it REQUIRES Forthink's COMMERCIAL UWB-Dongle-Sniffer hardware (an FT4222H-interfaced dongle) — the radio itself is a closed, purchased product, not open hardware. Listed for completeness as the most capable off-the-shelf UWB capture path; it observes frames, it does not defeat STS-protected ranging integrity." + "note": "Open-source host software and a Wireshark plugin (forthink-xyz/uwb-sniffer-wireshark) that monitor and decode CCC, FiRa and IEEE 802.15.4a/z UWB, including parameters for Apple Car-Key and AirTag/Nearby-Interaction (FiRa) traffic. Caveat: the software is open but it REQUIRES Forthink's COMMERCIAL UWB-Dongle-Sniffer hardware (an FT4222H-interfaced dongle), the radio itself is a closed, purchased product, not open hardware. Listed for completeness as the most capable off-the-shelf UWB capture path; it observes frames, it does not defeat STS-protected ranging integrity." }, { "slug": "forthink-uwb-dongle", @@ -77,6 +77,6 @@ "spec": "Commercial UWB sniffer dongle · FT4222H USB interface · closed hardware", "homepage": "https://github.com/forthink-xyz/forthink_uwb_sniffer_tool", "software": ["forthink-uwb-sniffer"], - "note": "Forthink's commercial UWB-Dongle-Sniffer — a closed, purchased FT4222H-interfaced UWB capture dongle (not open hardware). It is the radio the open Forthink sniffer software and Wireshark plugin run against; the dongle must be bought from Forthink." + "note": "Forthink's commercial UWB-Dongle-Sniffer, a closed, purchased FT4222H-interfaced UWB capture dongle (not open hardware). It is the radio the open Forthink sniffer software and Wireshark plugin run against; the dongle must be bought from Forthink." } ] diff --git a/src/data/protocol-tools/zigbee.json b/src/data/protocol-tools/zigbee.json index a6d2f88..6e41d71 100644 --- a/src/data/protocol-tools/zigbee.json +++ b/src/data/protocol-tools/zigbee.json @@ -6,7 +6,7 @@ "type": "software", "protocols": ["Zigbee", "802.15.4"], "repo": "https://github.com/riverloopsec/killerbee", - "note": "The reference IEEE 802.15.4 / Zigbee security toolkit. A Python framework plus command tools — zbstumbler (active network discovery), zbid (list capture interfaces), zbdump (capture to PCAP), zbwireshark (live feed to Wireshark), zbreplay (replay frames) and zbdsniff (extract a network key from a join capture). Drives a range of capture radios (ApiMote, CC2531, nRF52840, RZUSBstick).", + "note": "The reference IEEE 802.15.4 / Zigbee security toolkit. A Python framework plus command tools, zbstumbler (active network discovery), zbid (list capture interfaces), zbdump (capture to PCAP), zbwireshark (live feed to Wireshark), zbreplay (replay frames) and zbdsniff (extract a network key from a join capture). Drives a range of capture radios (ApiMote, CC2531, nRF52840, RZUSBstick).", "software": [] }, { @@ -16,7 +16,7 @@ "type": "software", "protocols": ["Zigbee"], "repo": "https://github.com/riverloopsec/killerbee", - "note": "KillerBee's key-extraction tool. Scans a capture for an over-the-air key transport (APS Transport-Key during a device join) and recovers the Zigbee network key — the classic break when the key is sent under the well-known default Trust Center link key 'ZigBeeAlliance09'. Feed it a PCAP of a join and it prints the network key.", + "note": "KillerBee's key-extraction tool. Scans a capture for an over-the-air key transport (APS Transport-Key during a device join) and recovers the Zigbee network key, the classic break when the key is sent under the well-known default Trust Center link key 'ZigBeeAlliance09'. Feed it a PCAP of a join and it prints the network key.", "software": [] }, { @@ -36,7 +36,7 @@ "type": "software", "protocols": ["Zigbee", "802.15.4"], "repo": "https://github.com/homewsn/whsniff", - "note": "Command-line utility that interfaces a TI CC2531 USB dongle with Wireshark to capture and display IEEE 802.15.4 traffic at 2.4 GHz — pipe its output into Wireshark (or save a PCAP) for Zigbee dissection. A cheap, simple capture path when you have a CC2531.", + "note": "Command-line utility that interfaces a TI CC2531 USB dongle with Wireshark to capture and display IEEE 802.15.4 traffic at 2.4 GHz, pipe its output into Wireshark (or save a PCAP) for Zigbee dissection. A cheap, simple capture path when you have a CC2531.", "software": [] }, { @@ -47,7 +47,7 @@ "protocols": ["Zigbee", "802.15.4"], "repo": "https://github.com/riverloopsec/apimote", "software": ["killerbee"], - "note": "IEEE 802.15.4 / Zigbee sniffing-and-injection hardware (CC2420-based) built as the reference KillerBee radio — it can both capture and transmit frames, which makes it the go-to board for KillerBee's active and attack tools (zbreplay, zbstumbler)." + "note": "IEEE 802.15.4 / Zigbee sniffing-and-injection hardware (CC2420-based) built as the reference KillerBee radio, it can both capture and transmit frames, which makes it the go-to board for KillerBee's active and attack tools (zbreplay, zbstumbler)." }, { "slug": "cc2531", @@ -58,6 +58,6 @@ "spec": "2.4 GHz 802.15.4 USB dongle · capture-only", "homepage": "https://www.ti.com/product/CC2531", "software": ["whsniff", "kismet"], - "note": "Cheap TI CC2531 USB dongle flashed with packet-sniffer firmware — a 2.4 GHz 802.15.4 capture-only radio (no injection). Bridged to Wireshark by whsniff." + "note": "Cheap TI CC2531 USB dongle flashed with packet-sniffer firmware, a 2.4 GHz 802.15.4 capture-only radio (no injection). Bridged to Wireshark by whsniff." } ] diff --git a/src/data/protocol-tools/zwave.json b/src/data/protocol-tools/zwave.json index 206d089..abec77f 100644 --- a/src/data/protocol-tools/zwave.json +++ b/src/data/protocol-tools/zwave.json @@ -16,7 +16,7 @@ "type": "software", "protocols": ["Z-Wave"], "repo": "https://github.com/andersesbensen/rtl-zwave", - "note": "The original G.9959 (Z-Wave) demodulator for the RTL-SDR: pipe `rtl_sdr` samples into it and it prints decoded Z-Wave frames. Lightweight, receive-only, and the codebase Waving-Z grew out of — a minimal way to confirm Z-Wave traffic and read frame headers on a ~$30 dongle.", + "note": "The original G.9959 (Z-Wave) demodulator for the RTL-SDR: pipe `rtl_sdr` samples into it and it prints decoded Z-Wave frames. Lightweight, receive-only, and the codebase Waving-Z grew out of, a minimal way to confirm Z-Wave traffic and read frame headers on a ~$30 dongle.", "software": [] }, { @@ -26,7 +26,7 @@ "type": "software", "protocols": ["Z-Wave"], "repo": "https://github.com/cureHsu/EZ-Wave", - "note": "The reference open Z-Wave assessment suite (GNU Radio + Scapy-radio): ezstumbler does passive discovery and active network enumeration, ezrecon interrogates a device (manufacturer/model, firmware version, supported command classes, configuration), and ezfingerprint identifies the Z-Wave module generation via a PHY preamble-length manipulation. Default config drives two HackRF One SDRs. Python 2.7 / GNU Radio 3.7 era — dated but still the canonical exploitation toolkit.", + "note": "The reference open Z-Wave assessment suite (GNU Radio + Scapy-radio): ezstumbler does passive discovery and active network enumeration, ezrecon interrogates a device (manufacturer/model, firmware version, supported command classes, configuration), and ezfingerprint identifies the Z-Wave module generation via a PHY preamble-length manipulation. Default config drives two HackRF One SDRs. Python 2.7 / GNU Radio 3.7 era, dated but still the canonical exploitation toolkit.", "software": [] }, { @@ -36,7 +36,7 @@ "type": "software", "protocols": ["Z-Wave"], "repo": "https://github.com/BastilleResearch/scapy-radio", - "note": "GNU Radio flowgraphs plus a patched Scapy that lets you sniff, dissect, craft and replay several sub-GHz/2.4 GHz protocols — including a Z-Wave layer — straight from a Python/Scapy session over an SDR (HackRF). The radio/Scapy plumbing EZ-Wave builds on, and a standalone way to script Z-Wave frame capture and injection.", + "note": "GNU Radio flowgraphs plus a patched Scapy that lets you sniff, dissect, craft and replay several sub-GHz/2.4 GHz protocols, including a Z-Wave layer, straight from a Python/Scapy session over an SDR (HackRF). The radio/Scapy plumbing EZ-Wave builds on, and a standalone way to script Z-Wave frame capture and injection.", "software": [] }, { @@ -56,7 +56,7 @@ "type": "software", "protocols": ["Z-Wave"], "homepage": "https://docs.silabs.com/z-wave/1.0.1/z-wave-docs/zwave-tools", - "note": "Silicon Labs' official GUI tool (in Simplicity Studio) that captures RF communication on a Z-Wave network for debugging — the vendor sniffer. Decodes the full Z-Wave frame including command classes and shows security (S0/S2) handshakes. Needs a USB Z-Wave adapter flashed with Zniffer firmware (e.g. a UZB stick). The turnkey capture path when an SDR demod is too fiddly.", + "note": "Silicon Labs' official GUI tool (in Simplicity Studio) that captures RF communication on a Z-Wave network for debugging, the vendor sniffer. Decodes the full Z-Wave frame including command classes and shows security (S0/S2) handshakes. Needs a USB Z-Wave adapter flashed with Zniffer firmware (e.g. a UZB stick). The turnkey capture path when an SDR demod is too fiddly.", "software": [] }, { @@ -66,7 +66,7 @@ "type": "software", "protocols": ["Z-Wave"], "homepage": "https://docs.silabs.com/z-wave/1.0.1/z-wave-docs/zwave-tools", - "note": "Silicon Labs' official GUI controller (Simplicity Studio): implements a Z-Wave controller node over the Serial API of a UZB USB adapter, so you can include/exclude nodes, browse the device's supported command classes and send them — driving a Z-Wave network legitimately from a PC. The application-layer counterpart to the Zniffer's capture.", + "note": "Silicon Labs' official GUI controller (Simplicity Studio): implements a Z-Wave controller node over the Serial API of a UZB USB adapter, so you can include/exclude nodes, browse the device's supported command classes and send them, driving a Z-Wave network legitimately from a PC. The application-layer counterpart to the Zniffer's capture.", "software": [] }, { @@ -78,6 +78,6 @@ "spec": "EFR32ZG14 Z-Wave 700 SoC · Serial API over USB (CP2102N VCOM) · firmware-upgradeable", "homepage": "https://www.silabs.com/development-tools/wireless/z-wave/efr32zg14-usb-7-z-wave-700-stick-bridge-module", "software": ["zwave-pc-controller", "zwave-zniffer"], - "note": "Silicon Labs' EFR32ZG14 USB stick that exposes the Z-Wave Serial API to a host — the controller adapter the Z-Wave PC Controller drives, and (re-flashed with Zniffer firmware) the capture adapter for the Z-Wave Zniffer. The official native-radio hardware for both vendor tools, ~US$21." + "note": "Silicon Labs' EFR32ZG14 USB stick that exposes the Z-Wave Serial API to a host, the controller adapter the Z-Wave PC Controller drives, and (re-flashed with Zniffer firmware) the capture adapter for the Z-Wave Zniffer. The official native-radio hardware for both vendor tools, ~US$21." } ] diff --git a/src/layouts/BaseLayout.astro b/src/layouts/BaseLayout.astro index fc4bb63..82fa636 100644 --- a/src/layouts/BaseLayout.astro +++ b/src/layouts/BaseLayout.astro @@ -17,7 +17,7 @@ const nav = [ - {title ? `${title} — RFSAM` : 'RFSAM'} + {title ? `${title}, RFSAM` : 'RFSAM'} @@ -31,7 +31,7 @@ const nav = [
    - {meta.title} — {meta.subtitle} · {meta.org} · {meta.version} · CC BY-SA 4.0 + {meta.title}, {meta.subtitle} · {meta.org} · {meta.version} · CC BY-SA 4.0
    diff --git a/src/pages/controls/[...slug].astro b/src/pages/controls/[...slug].astro index 481bdb3..bffed1c 100644 --- a/src/pages/controls/[...slug].astro +++ b/src/pages/controls/[...slug].astro @@ -13,7 +13,7 @@ import { layers } from '../../data/layers.js'; import { layerRank } from '../../lib/taxonomy.js'; // Order controls by the DESCENT (IG→SP→PHY→LL→CR→AT→AP), the way the methodology -// teaches them — not alphabetically by id. `layerRank` ranks IG=0 … AP=6; the index +// teaches them, not alphabetically by id. `layerRank` ranks IG=0 … AP=6; the index // additionally groups by protocol order. This also drives the prev/next pager. const prank = (pid) => protocols.findIndex((p) => p.id === pid); @@ -87,9 +87,9 @@ if (kind === 'control') {

    {kind === 'index' ? 'Controls' : protoName(protoId)}

    {kind === 'index' ? ( -

    A control verifies one thing for a single protocol × layer of the descent — a numbered, reproducible method with a worked field case, the known attacks with citations, and layered remediation. These are the entries you run during, and cite in, an assessment. Browse by technology in the sidebar, or pick one from the full list below.

    +

    A control verifies one thing for a single protocol × layer of the descent, a numbered, reproducible method with a worked field case, the known attacks with citations, and layered remediation. These are the entries you run during, and cite in, an assessment. Browse by technology in the sidebar, or pick one from the full list below.

    ) : ( -

    The {protoName(protoId)} controls — the descent for this technology step by step, each with its method, field case, known attacks and remediation.

    +

    The {protoName(protoId)} controls, the descent for this technology step by step, each with its method, field case, known attacks and remediation.

    )}
    colour = layer of the descent (IG → AP) diff --git a/src/pages/index.astro b/src/pages/index.astro index 35a4682..da919de 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -14,19 +14,19 @@ const techCount = Object.values(toolchains).filter((t) => t.status === 'complete const sections = [ { href: '/RFSAM/wayfinder', tag: 'START HERE', name: 'Wayfinder', accent: true, - body: 'Have a device or an unknown signal and no idea where to begin? Pick a technology and walk the six-step descent — each step hands you the exact kit (hardware + software) for that move and the reason to pick it. An interactive map from “what is this?” to “take it over.”', + body: 'Have a device or an unknown signal and no idea where to begin? Pick a technology and walk the six-step descent, each step hands you the exact kit (hardware + software) for that move and the reason to pick it. An interactive map from “what is this?” to “take it over.”', }, { href: '/RFSAM/controls', tag: 'THE REFERENCE', name: 'Controls', - body: 'The verification procedures. For each protocol and layer: what to check, a step-by-step method, a real field case, known attacks with references, and remediation — the entries you cite in an assessment.', + body: 'The verification procedures. For each protocol and layer: what to check, a step-by-step method, a real field case, known attacks with references, and remediation, the entries you cite in an assessment.', }, { href: '/RFSAM/methodology', tag: 'THE MODEL', name: 'Methodology', - body: 'The layer descent — spectrum → signal → link → crypto → attack → application — and the prior work RFSAM stands on (OSSTMM, BSAM, the SDR-pentest lineage). Read this to understand how it is organised.', + body: 'The layer descent, spectrum → signal → link → crypto → attack → application, and the prior work RFSAM stands on (OSSTMM, BSAM, the SDR-pentest lineage). Read this to understand how it is organised.', }, { href: '/RFSAM/tools', tag: 'THE KIT', name: 'Tools', - body: 'Every piece of hardware and software behind the wayfinder kits — filterable by technology and linked to its source.', + body: 'Every piece of hardware and software behind the wayfinder kits, filterable by technology and linked to its source.', }, ]; --- @@ -34,8 +34,8 @@ const sections = [
    Open methodology · {meta.org}

    A north for RF research and auditing.

    -

    RFSAM — {meta.subtitle}

    -

    A field guide to RF security — pick a technology, get the kit and the method.

    +

    RFSAM, {meta.subtitle}

    +

    A field guide to RF security, pick a technology, get the kit and the method.

    {meta.blurb}

    @@ -51,7 +51,7 @@ const sections = [

    THE DESCENT

    -

    Every protocol is assessed by the same descent — six layers from the open air down to what the device trusts. The Wayfinder walks you down it; the Controls verify each floor.

    +

    Every protocol is assessed by the same descent, six layers from the open air down to what the device trusts. The Wayfinder walks you down it; the Controls verify each floor.

    TECHNOLOGIES · {techCount} mapped in the Wayfinder

    diff --git a/src/pages/methodology.astro b/src/pages/methodology.astro index f300a93..2f3bd3e 100644 --- a/src/pages/methodology.astro +++ b/src/pages/methodology.astro @@ -10,7 +10,7 @@ const rubric = { low: 'A minor exposure or a hardening gap.', medium: 'A meaningful weakness that needs specific conditions to exploit.', high: 'A readily exploitable weakness with significant impact.', - critical: 'Full compromise — takeover, key recovery, impersonation — with practical preconditions.', + critical: 'Full compromise, takeover, key recovery, impersonation, with practical preconditions.', }; const ig = layers.find((l) => l.id === 'IG'); const descent = layers.filter((l) => l.id !== 'IG'); @@ -20,7 +20,7 @@ const descent = layers.filter((l) => l.id !== 'IG');

    Methodology

    RFSAM organises RF security on two axes. Every check is a control, indexed by the - protocol it applies to and by the layer of the assessment it belongs to — so, + protocol it applies to and by the layer of the assessment it belongs to, so, facing an unknown signal or device, you always have a place to start and a way to know what you've covered. It's a north, not a new attack: it ties OSSTMM, BSAM and the SDR-pentest lineage into one navigable reference across {protocols.length} technologies. @@ -28,7 +28,7 @@ const descent = layers.filter((l) => l.id !== 'IG');

    THE DESCENT

    - An assessment runs top-down through six layers — from the open air to what the device trusts — preceded by a + An assessment runs top-down through six layers, from the open air to what the device trusts, preceded by a pre-descent information-gathering pass. The Wayfinder walks you down it per technology; the controls verify each floor.

    @@ -52,7 +52,7 @@ const descent = layers.filter((l) => l.id !== 'IG');

    HOW A CONTROL IS BUILT

    Each control is identified as RFSAM-<PROTOCOL>-<LAYER>-NN - (e.g. RFSAM-BLE-AT-01) — its protocol × layer coordinates — and follows a fixed shape: + (e.g. RFSAM-BLE-AT-01), its protocol × layer coordinates, and follows a fixed shape: an objective (the one thing it verifies), a numbered procedure with real commands, a field case with real data, the known attacks with citations, and layered remediation. Every nontrivial claim carries a resolvable source; anything unverified is @@ -73,12 +73,12 @@ const descent = layers.filter((l) => l.id !== 'IG');

    Have a device and don't know where to start? Pick a technology and get the exact hardware + software kit - for each step of the descent — an action-first interactive map.

    + for each step of the descent, an action-first interactive map.

    Controls →
    -

    The reference body: the numbered, cited verification procedures — objective, method, field case, known - attacks, remediation — you run during, and cite in, an assessment.

    +

    The reference body: the numbered, cited verification procedures, objective, method, field case, known + attacks, remediation, you run during, and cite in, an assessment.

    @@ -96,7 +96,7 @@ const descent = layers.filter((l) => l.id !== 'IG'); ))}

    - Tarlogic BSAM ↗ — where BSAM owns a layer + Tarlogic BSAM ↗, where BSAM owns a layer (Bluetooth, link-and-above), the BLE controls defer to it and add only the RF-capture prerequisite, citing the specific BSAM control they hand off to.

    diff --git a/src/pages/roadmap.astro b/src/pages/roadmap.astro index c7acd99..30b7b4f 100644 --- a/src/pages/roadmap.astro +++ b/src/pages/roadmap.astro @@ -50,9 +50,9 @@ const realCount = heat.reduce((n, r) => n + r.cells.filter((c) => c.state === 'r

    Roadmap

    - RFSAM is built in two tracks. The Wayfinder — the interactive - per-technology kits — is complete across the technologies below. The Controls - — the written verification procedures, with field cases and remediation — are authored and citation-verified across + RFSAM is built in two tracks. The Wayfinder, the interactive + per-technology kits, is complete across the technologies below. The Controls + , the written verification procedures, with field cases and remediation, are authored and citation-verified across the protocols below; most field cases are still illustrative templates until real captures replace them.

    @@ -72,7 +72,7 @@ const realCount = heat.reduce((n, r) => n + r.cells.filter((c) => c.state === 'r

    Controls {existingCount} written · {realCount} verified · {gapCount} open gaps · {plannedCount} planned

    - RFSAM grows by pull request. This heatmap is the honest state of coverage — every cell is a + RFSAM grows by pull request. This heatmap is the honest state of coverage, every cell is a protocol × layer of the descent, so you can see exactly what exists and what doesn't. The amber cells are where the Wayfinder already names the kit but no control is written yet: the best place to start. Read @@ -89,12 +89,12 @@ const realCount = heat.reduce((n, r) => n + r.cells.filter((c) => c.state === 'r {row.p.name} {row.cells.map((c) => { - const desc = { real: 'control with a real field case', illus: 'control — illustrative field case (needs a real capture)', gap: 'Wayfinder kit exists, control not written yet — help wanted', none: 'not yet scoped' }[c.state]; + const desc = { real: 'control with a real field case', illus: 'control, illustrative field case (needs a real capture)', gap: 'Wayfinder kit exists, control not written yet, help wanted', none: 'not yet scoped' }[c.state]; const href = (c.state === 'real' || c.state === 'illus') ? (c.ids.length === 1 ? `/RFSAM/controls/${c.ids[0].toLowerCase()}` : `/RFSAM/controls/${row.p.id.toLowerCase()}`) : c.state === 'gap' ? `/RFSAM/wayfinder/${row.p.id.toLowerCase()}` : null; const sym = { real: '●', illus: '◐', gap: '+', none: '' }[c.state]; - const title = `${row.p.name} · ${c.lid} — ${desc}`; + const title = `${row.p.name} · ${c.lid}, ${desc}`; return href ? {sym} :

    {sym}
    ; @@ -104,9 +104,9 @@ const realCount = heat.reduce((n, r) => n + r.cells.filter((c) => c.state === 'r
    - verified — real field case - reviewed — illustrative field case (needs a real capture) - kit ready — control unwritten (help wanted) + verified, real field case + reviewed, illustrative field case (needs a real capture) + kit ready, control unwritten (help wanted) not yet scoped
    diff --git a/src/pages/tools.astro b/src/pages/tools.astro index 5b7096b..2ea5023 100644 --- a/src/pages/tools.astro +++ b/src/pages/tools.astro @@ -13,7 +13,7 @@ const CHIP = { ZIGBEE: 'Zigbee', ZWAVE: 'Z-Wave', THREAD: 'Thread', GNSS: 'GNSS', ADSB: 'ADS-B', NR5G: '5G NR', GSM: 'GSM', UWB: 'UWB', }; -// Which technologies actually USE each tool — derived from the wayfinder toolchains +// Which technologies actually USE each tool, derived from the wayfinder toolchains // (a tool's step + dep + decoder membership), NOT from blanket tags. So SDRs show // under BLE/LTE/Sub-GHz where they're used, but not under near-field RFID/NFC. const techByTool = {}; @@ -35,7 +35,7 @@ const chips = Object.keys(CHIP).map((id) => ({ id, label: CHIP[id], n: tools.fil

    Tools

    - The hardware and software behind the wayfinder kits. Hardware first — open a device to see the software that + The hardware and software behind the wayfinder kits. Hardware first, open a device to see the software that pairs with it. Representative, not exhaustive; check current advisories. Repo links go to each project's source.

    diff --git a/src/pages/tools/[slug].astro b/src/pages/tools/[slug].astro index d9c4bed..7ea23e5 100644 --- a/src/pages/tools/[slug].astro +++ b/src/pages/tools/[slug].astro @@ -22,7 +22,7 @@ const link = tool.repo ?? tool.homepage; // Compatible software declared on this hardware tool. const compatible = (tool.software ?? []).map(bySlug).filter(Boolean); -// Where this tool appears in a technology's toolchain — as the primary tool, as a +// Where this tool appears in a technology's toolchain, as the primary tool, as a // dependency (the hardware a tool runs on), or as the step's decoder. const usedIn = []; for (const [proto, tc] of Object.entries(toolchains)) { diff --git a/src/pages/wayfinder/[protocol].astro b/src/pages/wayfinder/[protocol].astro index 2d785a6..68f09c7 100644 --- a/src/pages/wayfinder/[protocol].astro +++ b/src/pages/wayfinder/[protocol].astro @@ -93,7 +93,7 @@ const payload = JSON.stringify({ // ---- pinned pipeline layout: step (spine) → software → hardware, plus a shared decoder ---- const X1 = 86, NODE_VG = 28, MIN_SLOT = 92, STEP_PAD = 32, CHAR_W = 11, COL_GAP = 40; // Columns scale to the longest label so software roles can't overrun the hardware - // column — decoder at X1, software at swCol, hardware at hwCol. + // column, decoder at X1, software at swCol, hardware at hwCol. let maxDec = 0, maxSw = 0, anyDec = false; P.steps.forEach((s) => { if (s.decoder) { anyDec = true; maxDec = Math.max(maxDec, s.decoder.name.length); } @@ -127,7 +127,7 @@ const payload = JSON.stringify({ nodes.push({ id: decId, name: s.decoder.name, kind: s.decoder.type, stepKey: s.key, x: X1, y: cy, fx: X1, fy: cy, detail: { kind: 'tool', tool: { ...s.decoder, role: 'Decode', why: s.decoder.note, caveat: null, needs: null, deps: [] } } }); links.push({ source: sid, target: decId }); // Capture step → Wireshark (the entry) } - // Key each tool node by its ENTRY index, not its slug — a step may list the + // Key each tool node by its ENTRY index, not its slug, a step may list the // same tool twice (e.g. Proxmark for two roles), and slug-keyed ids would // collide, leaving one bubble unlinked/floating. idForSlug resolves a // dep that points at another primary tool to that tool's first node. @@ -137,7 +137,7 @@ const payload = JSON.stringify({ const ty = cy + (j - (n1 - 1) / 2) * NODE_VG; const tid = sid + ':t:' + j; // label the node by its ROLE (the capability at this step) so the graph itself - // explains what you do — e.g. "Channel activity & topology (cativity)" rather + // explains what you do, e.g. "Channel activity & topology (cativity)" rather // than just "catnip"; fall back to the tool name when a tool has no role. const label = t.role || t.name; nodes.push({ id: tid, name: label, kind: t.type, stepKey: s.key, x: softwareX, y: ty, fx: softwareX, fy: ty, detail: { kind: 'tool', tool: t } }); @@ -233,9 +233,9 @@ const payload = JSON.stringify({ ${planned ? `

    ${esc(P.protocol.name)}'s toolchain is still being filled in. The descent and controls are here; the kit lands when the tools are curated.

    ` : ''} ${P.protocol.reference ? `
    ${linkA(P.protocol.reference.url, 'Reference: ' + esc(P.protocol.reference.name) + ' ↗')}
    ` : ''}
    Hardware tools${hw.length}
    -
    ${hw.map(kitRow).join('') || '—'}
    +
    ${hw.map(kitRow).join('') || '·'}
    Software tools${sw.length}
    -
    ${sw.map(kitRow).join('') || '—'}
    +
    ${sw.map(kitRow).join('') || '·'}

    Click a step, software or hardware node for the reasons and the detail.

    `; } @@ -269,7 +269,7 @@ const payload = JSON.stringify({ } side.innerHTML = h; document.getElementById('wf-back').onclick = renderKit; - // On phones the panel sits BELOW the graph — bring it into view on a tap so + // On phones the panel sits BELOW the graph, bring it into view on a tap so // the detail you just asked for is actually on screen. if (window.matchMedia('(max-width: 760px)').matches) { document.getElementById('wf-side').scrollIntoView({ behavior: 'smooth', block: 'start' }); From 56b29ed4500ae4585c6596b2b90e45bf02c2f5a2 Mon Sep 17 00:00:00 2001 From: Eduardo Contreras Date: Mon, 28 Sep 2026 17:05:09 -0600 Subject: [PATCH 3/5] Restore code strings, placeholders and cited titles changed by the dash removal --- src/content/controls/rfsam-adsb-phy-01.md | 2 +- src/content/controls/rfsam-gnss-at-01.md | 2 +- src/content/controls/rfsam-gsm-cr-01.md | 2 +- src/content/controls/rfsam-lte-phy-01.md | 2 +- src/content/controls/rfsam-lte-sp-01.md | 2 +- src/content/controls/rfsam-rfid-cr-01.md | 4 ++-- src/content/controls/rfsam-rfid-sp-01.md | 2 +- src/content/controls/rfsam-subg-ll-01.md | 2 +- src/content/controls/rfsam-thread-cr-01.md | 2 +- src/content/controls/rfsam-zwave-sp-01.md | 2 +- 10 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/content/controls/rfsam-adsb-phy-01.md b/src/content/controls/rfsam-adsb-phy-01.md index aeecefd..d2d841e 100644 --- a/src/content/controls/rfsam-adsb-phy-01.md +++ b/src/content/controls/rfsam-adsb-phy-01.md @@ -236,7 +236,7 @@ modes decode 8D40058B58C901375147EFD09357 --reference 49.0 6.0 These are the canonical pyModeS test vectors, so the expected outputs are stable: a `40058B` position near the 49.0 N, 6.0 E reference and the `406B90` / `EZY85MH` -identity. This is the verifiable, reproducible core of the field case — the decode +identity. This is the verifiable, reproducible core of the field case, the decode chain confirmed against fixed, published frames, with no air capture or transmitter required. diff --git a/src/content/controls/rfsam-gnss-at-01.md b/src/content/controls/rfsam-gnss-at-01.md index 2c31398..4442e5d 100644 --- a/src/content/controls/rfsam-gnss-at-01.md +++ b/src/content/controls/rfsam-gnss-at-01.md @@ -85,7 +85,7 @@ references: url: 'https://doi.org/10.1109/JPROC.2016.2526658' type: paper - key: texbat - title: 'TEXBAT, Texas Spoofing Test Battery (civil GPS L1 C/A spoofing recordings)' + title: 'TEXBAT: Texas Spoofing Test Battery (civil GPS L1 C/A spoofing recordings)' authors: 'T. E. Humphreys, J. A. Bhatti, D. P. Shepard, K. D. Wesson (UT Austin Radionavigation Laboratory)' venue: UT Austin Radionavigation Laboratory year: 2012 diff --git a/src/content/controls/rfsam-gsm-cr-01.md b/src/content/controls/rfsam-gsm-cr-01.md index 53a1fc2..854fd3a 100644 --- a/src/content/controls/rfsam-gsm-cr-01.md +++ b/src/content/controls/rfsam-gsm-cr-01.md @@ -93,7 +93,7 @@ references: url: 'https://www.iacr.org/archive/crypto2003/27290598/27290598.pdf' type: paper - key: nohl2009gsm - title: GSM, SRSLY? (A5/1 rainbow tables / Berlin A5/1 Security Project) + title: 'GSM: SRSLY? (A5/1 rainbow tables / Berlin A5/1 Security Project)' authors: 'K. Nohl, C. Paget' venue: 26th Chaos Communication Congress (26C3), Berlin year: 2009 diff --git a/src/content/controls/rfsam-lte-phy-01.md b/src/content/controls/rfsam-lte-phy-01.md index 66902f6..667c976 100644 --- a/src/content/controls/rfsam-lte-phy-01.md +++ b/src/content/controls/rfsam-lte-phy-01.md @@ -140,7 +140,7 @@ All steps below are passive reception only. LTE is licensed spectrum: receiving Illustrative walkthrough, substitute the values you capture; this is a reproducible example, not a measured engagement, and every unmeasured quantity is marked `[FILL: …]`. -Rig: a USRP B210 with the GPSDO option, fed a band-3 (1800 MHz FDD) downlink. After `uhd_usrp_probe` confirms the GPSDO reference, `cell_search -b 3` returns a `Found CELL` line reporting `EARFCN=[FILL: e.g. 1500]`, `PHYID=[FILL: PCI 0 to 503]`, `[FILL: nof] PRB`, and `PSS power=[FILL: dBm]`. Pointing `pdsch_ue -f [FILL: RX Hz] -A 2` at that carrier produces a steady `Decoded MIB. SFN: [FILL]` and, at subframe 5, `PDCCH-Miss: [FILL: %]` / `PDSCH-BLER: [FILL: %]`. The control passes when synchronisation holds, the PCI is stable across repeated runs, and the grid demodulates without timing-induced corruption. +Rig: a USRP B210 with the GPSDO option, fed a band-3 (1800 MHz FDD) downlink. After `uhd_usrp_probe` confirms the GPSDO reference, `cell_search -b 3` returns a `Found CELL` line reporting `EARFCN=[FILL: e.g. 1500]`, `PHYID=[FILL: PCI 0-503]`, `[FILL: nof] PRB`, and `PSS power=[FILL: dBm]`. Pointing `pdsch_ue -f [FILL: RX Hz] -A 2` at that carrier produces a steady `Decoded MIB. SFN: [FILL]` and, at subframe 5, `PDCCH-Miss: [FILL: %]` / `PDSCH-BLER: [FILL: %]`. The control passes when synchronisation holds, the PCI is stable across repeated runs, and the grid demodulates without timing-induced corruption. A documented degradation pattern worth reproducing: the *same* recorded carrier that decoded MIB cleanly on a desktop host failed intermittently on an underpowered mini-PC, the SDR was fine, but host I/O could not sustain the sample rate, surfacing as `Cell not found` retries and elevated PDCCH-Miss. This is the practical lesson of RFSAM-RES-09: coherent OFDM capture is bounded by the *whole* chain (reference clock and host throughput), not the radio alone. diff --git a/src/content/controls/rfsam-lte-sp-01.md b/src/content/controls/rfsam-lte-sp-01.md index 634a78d..7be5b71 100644 --- a/src/content/controls/rfsam-lte-sp-01.md +++ b/src/content/controls/rfsam-lte-sp-01.md @@ -130,7 +130,7 @@ That same unprotected broadcast and pre-authentication information is what an at ```text AT+CPSI? ``` - Per the SIMCom AT command manual the LTE read returns `LTE,,-,,,,,,,...`, i.e. operator, Tracking Area Code, serving-cell ID, PCI, band and EARFCN on one line, e.g. `+CPSI: LTE,Online,-,0x,,,EUTRAN-BAND,...`. For a deeper, still-passive read of the broadcast/paging the modem already receives, stream its Diag port into Wireshark with QCSuper [qcsuper]. + Per the SIMCom AT command manual the LTE read returns `LTE,,-,,,,,,,,...`, i.e. operator, Tracking Area Code, serving-cell ID, PCI, band and EARFCN on one line, e.g. `+CPSI: LTE,Online,-,0x,,,EUTRAN-BAND,,...`. For a deeper, still-passive read of the broadcast/paging the modem already receives, stream its Diag port into Wireshark with QCSuper [qcsuper]. 5. **Record the inventory.** For each cell, capture: operator (PLMN MCC-MNC), band, downlink EARFCN, PCI, system bandwidth and TAC. Mark which cells fall inside your SDR's tuning and instantaneous-bandwidth envelope, those are the sniffable targets that scope the later LTE capture controls (RFSAM-RES-08). diff --git a/src/content/controls/rfsam-rfid-cr-01.md b/src/content/controls/rfsam-rfid-cr-01.md index c99b0db..5181741 100644 --- a/src/content/controls/rfsam-rfid-cr-01.md +++ b/src/content/controls/rfsam-rfid-cr-01.md @@ -102,7 +102,7 @@ references: url: 'https://doi.org/10.1109/SP.2009.6' type: paper - key: courtois2009darkside - title: 'The Dark Side of Security by Obscurity: and Cloning MiFare Classic Rail and Building Passes, Anywhere, Anytime' + title: 'The Dark Side of Security by Obscurity and Cloning MiFare Classic Rail and Building Passes Anywhere, Anytime' authors: N. T. Courtois venue: 'SECRYPT 2009 / IACR ePrint 2009/137' year: 2009 @@ -276,7 +276,7 @@ sec | key A | key B | access | note 1 | D203A62D6106 | 602A34A75AA4 | 787788 | both non-default 2 | A0A1A2A3A4A5 | 0000014B5C31 | 0F00FF | key B non-default 6 | FFFFFFFFFFFF | 96A301BCE267 | 0F00FF | key B non-default - 3 to 5, 7 to 15 | default FFFFFFFFFFFF / FFFFFFFFFFFF + 3-5, 7-15 | default FFFFFFFFFFFF / FFFFFFFFFFFF hidden config sector | key A 3E64977BDF58 | key B 00005BF0055A ``` diff --git a/src/content/controls/rfsam-rfid-sp-01.md b/src/content/controls/rfsam-rfid-sp-01.md index f622054..e2ca6f0 100644 --- a/src/content/controls/rfsam-rfid-sp-01.md +++ b/src/content/controls/rfsam-rfid-sp-01.md @@ -79,7 +79,7 @@ references: url: 'https://doi.org/10.1109/SP.2009.6' type: paper - key: courtois2009darkside - title: 'The Dark Side of Security by Obscurity: and Cloning MiFare Classic Rail and Building Passes, Anywhere, Anytime' + title: 'The Dark Side of Security by Obscurity and Cloning MiFare Classic Rail and Building Passes Anywhere, Anytime' authors: N. T. Courtois venue: SECRYPT 2009 year: 2009 diff --git a/src/content/controls/rfsam-subg-ll-01.md b/src/content/controls/rfsam-subg-ll-01.md index 2922024..281f964 100644 --- a/src/content/controls/rfsam-subg-ll-01.md +++ b/src/content/controls/rfsam-subg-ll-01.md @@ -153,7 +153,7 @@ The canonical example of a fixed address is the EV1527/PT2262 OOK encoder family ```bash rtl_433 -f 433.92M -F json ``` - Expected: one JSON line per burst, e.g. `{"model":"...","id":12345,"channel":1...}`. The `id` is the recovered link-layer address; `model` names the protocol/field layout for free [rtl433] [rtl433dataformat]. If nothing decodes, energy is present but the class is unknown, go to step 2. + Expected: one JSON line per burst, e.g. `{"model":"...","id":12345,"channel":1,...}`. The `id` is the recovered link-layer address; `model` names the protocol/field layout for free [rtl433] [rtl433dataformat]. If nothing decodes, energy is present but the class is unknown, go to step 2. 2. **Record raw bursts for an unknown frame.** Capture I/Q at the carrier and bandwidth found at the Spectrum/PHY steps (RFSAM-RES-15), triggering the device several times: ```bash diff --git a/src/content/controls/rfsam-thread-cr-01.md b/src/content/controls/rfsam-thread-cr-01.md index c5e2381..c978921 100644 --- a/src/content/controls/rfsam-thread-cr-01.md +++ b/src/content/controls/rfsam-thread-cr-01.md @@ -184,7 +184,7 @@ Run every active or decrypt step only against your own equipment, test devices, This walkthrough is grounded in the Matter SDK's own documented example onboarding payload, so the decoded values below are public reference data, not a measured engagement against a third-party device. Any value still marked `[FILL: …]` is a capture-specific placeholder and must not be treated as an observed finding. -The Matter SDK's chip-tool guide documents how to recover a device's onboarding parameters from its printed payload, using the SDK reference example payload, QR `MT:Y.K9042C00KA0648G00` / manual pairing code `749701123365521327694`, as its worked case [matter-chip-tool-guide]. Decoding that payload (the guide's "Step 5: Determine Matter device's discriminator and setup PIN code") yields a setup passcode of `20202021`, discriminator `3840 (0xF00)`, Vendor Id `65521 (0xFFF1)` and Product Id `32768 (0x8000)` [matter-chip-tool-guide]. An 802.15.4 capture on channel `[FILL: channel 11 to 26]` shows 6LoWPAN + MLE frames, confirming Thread, not Zigbee, with the MAC payload encrypted; without the network key, Wireshark leaves the payloads opaque (the expected, healthy state). +The Matter SDK's chip-tool guide documents how to recover a device's onboarding parameters from its printed payload, using the SDK reference example payload, QR `MT:Y.K9042C00KA0648G00` / manual pairing code `749701123365521327694`, as its worked case [matter-chip-tool-guide]. Decoding that payload (the guide's "Step 5: Determine Matter device's discriminator and setup PIN code") yields a setup passcode of `20202021`, discriminator `3840 (0xF00)`, Vendor Id `65521 (0xFFF1)` and Product Id `32768 (0x8000)` [matter-chip-tool-guide]. An 802.15.4 capture on channel `[FILL: channel 11-26]` shows 6LoWPAN + MLE frames, confirming Thread, not Zigbee, with the MAC payload encrypted; without the network key, Wireshark leaves the payloads opaque (the expected, healthy state). With a commissioning window open, the same guide drives PASE over BLE onto Thread with that on-label code via `./chip-tool pairing ble-thread 1 hex: 20202021 3840`, where `20202021` is the decoded setup passcode and `3840` the discriminator [matter-chip-tool-guide]. A successful pairing returns the operational Thread dataset, which then decrypts the capture in Wireshark, demonstrating that the entire chain hinges on the setup code, not on the AES-CCM* link layer. The audit question that determines criticality is whether that passcode is a unique high-entropy per-device value or a shared/guessable default. Here it is the latter: `20202021` (with discriminator `3840` and VID/PID `0xFFF1/0x8000`) is the SDK's shared example/test value, baked into the reference apps and reused across SDK documentation and sample builds [matter-chip-tool-guide], exactly the kind of common, non-unique credential a real device must never ship, so on production hardware its presence would be a genuine exposure rather than a hardening note. diff --git a/src/content/controls/rfsam-zwave-sp-01.md b/src/content/controls/rfsam-zwave-sp-01.md index 61c1daf..3df79d7 100644 --- a/src/content/controls/rfsam-zwave-sp-01.md +++ b/src/content/controls/rfsam-zwave-sp-01.md @@ -56,7 +56,7 @@ references: url: 'https://www.silabs.com/wireless/z-wave/z-wave-long-range-overview' type: standard - key: fouladi2013honey - title: "Honey, I'm Home!!: Hacking Z-Wave Home Automation Systems (Black Hat USA 2013, recorded talk)" + title: "Honey, I'm Home!! - Hacking Z-Wave Home Automation Systems (Black Hat USA 2013, recorded talk)" authors: Behrang Fouladi, Sahand Ghanoun (SensePost) venue: Black Hat USA 2013 year: 2013 From fa8dd14b82776cb5ef1f8c920d4e8fdc2e68f409 Mon Sep 17 00:00:00 2001 From: Eduardo Contreras Date: Mon, 28 Sep 2026 17:05:09 -0600 Subject: [PATCH 4/5] Remove dashes from the tool seed and regenerate the tool pages --- scripts/seed-tools.mjs | 50 +++++++++---------- src/content/tools/5greplay.md | 4 +- src/content/tools/adsb-out.md | 10 ++-- src/content/tools/chirpstack.md | 5 +- src/content/tools/cyd.md | 2 +- src/content/tools/dwm3000-dwt-driver.md | 4 +- src/content/tools/dwm3000evb.md | 5 +- src/content/tools/esp32-bt-classic-sniffer.md | 12 ++--- src/content/tools/esp32-bt-exp.md | 4 +- src/content/tools/esp32-classic-bt-scan.md | 8 +-- src/content/tools/esp32-sour-apple.md | 4 +- src/content/tools/evilapplejuice-esp32.md | 3 +- src/content/tools/ez-wave.md | 4 +- src/content/tools/flipper-wifi-devboard.md | 2 +- src/content/tools/flipper-zero.md | 13 ++--- src/content/tools/gps-sdr-sim.md | 4 +- src/content/tools/gpsd.md | 9 ++-- src/content/tools/hackrf-one.md | 6 +-- src/content/tools/hostapd-mana.md | 6 +-- src/content/tools/kismet.md | 4 +- src/content/tools/libnfc.md | 3 +- src/content/tools/matter-dcl.md | 4 +- src/content/tools/murata-type2bp.md | 14 +++--- src/content/tools/openairinterface5g.md | 6 +-- src/content/tools/pymodes.md | 6 +-- src/content/tools/python-matter-server.md | 6 +-- src/content/tools/qcsuper.md | 4 +- src/content/tools/rak-wisgate-connect.md | 4 +- src/content/tools/silabs-uzb7.md | 7 +-- src/content/tools/yard-stick-one.md | 4 +- 30 files changed, 111 insertions(+), 106 deletions(-) diff --git a/scripts/seed-tools.mjs b/scripts/seed-tools.mjs index 1fee54b..564fcda 100644 --- a/scripts/seed-tools.mjs +++ b/scripts/seed-tools.mjs @@ -9,36 +9,36 @@ const tools = [ // ---- hardware ---- { slug: 'hackrf-one', name: 'HackRF One', vendor: 'Great Scott Gadgets', type: 'hardware', - protocols: ['Wide-band SDR'], spec: '~20 MHz IBW · 1 MHz–6 GHz · half-duplex', + protocols: ['Wide-band SDR'], spec: '~20 MHz IBW · 1 MHz to 6 GHz · half-duplex', repo: 'https://github.com/greatscottgadgets/hackrf', software: ['universal-radio-hacker', 'ice9-bluetooth-sniffer'], - note: "1 MHz–6 GHz half-duplex SDR — the discovery radio for 'Rapid Radio Reversing': find and characterise an unknown signal before working it with a narrowband tool.", + note: "1 MHz to 6 GHz half-duplex SDR, the discovery radio for 'Rapid Radio Reversing': find and characterise an unknown signal before working it with a narrowband tool.", }, { slug: 'bladerf-2-micro', name: 'bladeRF 2.0 micro xA9', vendor: 'Nuand', type: 'hardware', - protocols: ['Wide-band SDR'], spec: '56 MHz IBW · up to 122.88 MHz oversampled (8-bit) · 47 MHz–6 GHz', + protocols: ['Wide-band SDR'], spec: '56 MHz IBW · up to 122.88 MHz oversampled (8-bit) · 47 MHz to 6 GHz', homepage: 'https://www.nuand.com/2023-02-release-122-88mhz-bandwidth/', software: ['ice9-bluetooth-sniffer'], - note: 'Wideband full-duplex SDR (AD9361). ~56 MHz standard, and since the 2023.02 release an oversampling mode reaches 122.88 MHz instantaneous bandwidth (at 8-bit depth over USB 3.0) — enough to cover the entire 80 MHz BLE band in a single pass.', + note: 'Wideband full-duplex SDR (AD9361). ~56 MHz standard, and since the 2023.02 release an oversampling mode reaches 122.88 MHz instantaneous bandwidth (at 8-bit depth over USB 3.0), enough to cover the entire 80 MHz BLE band in a single pass.', }, { slug: 'usrp-b210', name: 'USRP B210', vendor: 'Ettus Research (NI)', type: 'hardware', - protocols: ['Wide-band SDR'], spec: '~56 MHz IBW (30.72 MHz in 2×2) · 70 MHz–6 GHz', + protocols: ['Wide-band SDR'], spec: '~56 MHz IBW (30.72 MHz in 2×2) · 70 MHz to 6 GHz', homepage: 'https://www.ettus.com/all-products/ub210-kit/', software: ['ice9-bluetooth-sniffer'], note: 'Lab-grade full-duplex SDR (AD9361) with a disciplined clock option. Up to ~56 MHz real-time bandwidth (halved to ~30.72 MHz in 2×2 MIMO). A common ice9 target for BLE/BT capture.', }, { slug: 'signalsdr-pro', name: 'SignalSDR Pro', vendor: 'Signalens', type: 'hardware', - protocols: ['Wide-band SDR'], spec: '61.44 MHz BW · 70 MHz–6 GHz · 2TX/2RX', + protocols: ['Wide-band SDR'], spec: '61.44 MHz BW · 70 MHz to 6 GHz · 2TX/2RX', homepage: 'https://www.rtl-sdr.com/signalsdr-pro-an-upcoming-sdr-with-70-mhz-to-6-ghz-12-bit-adc-61-44-mhz-bandwidth-and-2tx-2rx-channels/', - note: 'AD9361-based SDR in a Raspberry-Pi form factor (Zynq 7020); the widest instantaneous bandwidth in this list at 61.44 MHz, and it can emulate a USRP B210 / ADALM-Pluto. Newer/emerging product — verify ice9 support and availability before relying on it.', + note: 'AD9361-based SDR in a Raspberry-Pi form factor (Zynq 7020); the widest instantaneous bandwidth in this list at 61.44 MHz, and it can emulate a USRP B210 / ADALM-Pluto. Newer/emerging product, verify ice9 support and availability before relying on it.', }, { slug: 'rtl-sdr-v4', name: 'RTL-SDR Blog V4', vendor: 'RTL-SDR Blog', type: 'hardware', - protocols: ['RX-only SDR'], spec: '~2.4 MHz BW · 0.5 kHz–1.766 GHz · RX only', + protocols: ['RX-only SDR'], spec: '~2.4 MHz BW · 0.5 kHz to 1.766 GHz · RX only', homepage: 'https://www.rtl-sdr.com/v4/', - note: 'Budget RX-only dongle. Does NOT reach 2.4 GHz, so it cannot receive BLE, Wi-Fi or Zigbee — but it is a fine cheap receiver for sub-GHz, LoRa and ADS-B (1090 MHz).', + note: 'Budget RX-only dongle. Does NOT reach 2.4 GHz, so it cannot receive BLE, Wi-Fi or Zigbee, but it is a fine cheap receiver for sub-GHz, LoRa and ADS-B (1090 MHz).', }, { slug: 'ubertooth-one', name: 'Ubertooth One', vendor: 'Great Scott Gadgets', type: 'hardware', @@ -56,7 +56,7 @@ const tools = [ slug: 'yard-stick-one', name: 'YARD Stick One', vendor: 'Great Scott Gadgets', type: 'hardware', protocols: ['Sub-GHz'], homepage: 'https://greatscottgadgets.com/yardstickone/', software: ['rfcat', 'universal-radio-hacker'], - note: 'CC1111 sub-GHz transceiver (300–928 MHz) driven by rfcat — receive, replay and transmit OOK/ASK/FSK from a Python shell. The reference cheap Sub-GHz work tool, paired with a HackRF for discovery.', + note: 'CC1111 sub-GHz transceiver (300 to 928 MHz) driven by rfcat, receive, replay and transmit OOK/ASK/FSK from a Python shell. The reference cheap Sub-GHz work tool, paired with a HackRF for discovery.', }, { slug: 'proxmark3', name: 'Proxmark3', vendor: 'RFID Research Group (Iceman fork)', type: 'hardware', @@ -72,7 +72,7 @@ const tools = [ slug: 'alfa-awus036ach', name: 'ALFA AWUS036ACH', vendor: 'Alfa Network', type: 'hardware', protocols: ['Wi-Fi'], homepage: 'https://alfa-network.com/products/awus036ach', software: ['aircrack-ng', 'bettercap', 'wireshark'], - note: 'RTL8812AU dual-band Wi-Fi adapter with monitor mode and injection — the workhorse 802.11 capture/injection radio for surveys and handshake capture.', + note: 'RTL8812AU dual-band Wi-Fi adapter with monitor mode and injection, the workhorse 802.11 capture/injection radio for surveys and handshake capture.', }, { slug: 'wifi-pineapple', name: 'WiFi Pineapple', vendor: 'Hak5', type: 'hardware', @@ -87,7 +87,7 @@ const tools = [ { slug: 'minino', name: 'Minino', vendor: 'Electronic Cats', type: 'hardware', ec: true, protocols: ['Wi-Fi', 'BLE', 'Zigbee', 'Thread'], repo: 'https://github.com/ElectronicCats/Minino', - note: 'ESP32-C6 pocket multitool (GPS, microSD, OLED). For Wi-Fi (2.4 GHz only) it does wardriving, an AP/SSID sniffer with Wireshark-compatible output, a deauther and console-driven DoS, an analyzer, SSID spammer, and Wi-Fi deauthentication detection. It also has a native BLE suite — an advertising scanner, tracker/AirTag detection, BLE notification spam and BLE HID — plus 802.15.4 (Zigbee/Thread) field recon.', + note: 'ESP32-C6 pocket multitool (GPS, microSD, OLED). For Wi-Fi (2.4 GHz only) it does wardriving, an AP/SSID sniffer with Wireshark-compatible output, a deauther and console-driven DoS, an analyzer, SSID spammer, and Wi-Fi deauthentication detection. It also has a native BLE suite, an advertising scanner, tracker/AirTag detection, BLE notification spam and BLE HID, plus 802.15.4 (Zigbee/Thread) field recon.', }, { slug: 'nrf52840-dongle', name: 'nRF52840 Dongle', vendor: 'Nordic Semiconductor', type: 'hardware', @@ -97,7 +97,7 @@ const tools = [ { slug: 'bbc-microbit', name: 'BBC micro:bit', vendor: 'Micro:bit Educational Foundation', type: 'hardware', protocols: ['BLE'], homepage: 'https://microbit.org', software: ['btlejack'], - note: 'A ~$15 nRF51822 board — the reference cheap radio for running Btlejack to sniff, jam and hijack BLE connections.', + note: 'A ~$15 nRF51822 board, the reference cheap radio for running Btlejack to sniff, jam and hijack BLE connections.', }, { @@ -105,24 +105,24 @@ const tools = [ protocols: ['LoRa', 'Sub-GHz'], spec: 'STM32WL SoC · integrated sub-GHz LoRa/(G)FSK radio', homepage: 'https://github.com/whad-team/stm32wlxx-firmware', software: ['whad'], - note: "Any STM32WLxx-based board (e.g. Nucleo-WL55JC, Seeed LoRa-E5) — an Arm Cortex-M4 with an integrated sub-GHz radio. Flashed with WHAD's stm32wlxx-firmware it becomes a WHAD-driven LoRa/LoRaWAN sniff-and-inject radio.", + note: "Any STM32WLxx-based board (e.g. Nucleo-WL55JC, Seeed LoRa-E5), an Arm Cortex-M4 with an integrated sub-GHz radio. Flashed with WHAD's stm32wlxx-firmware it becomes a WHAD-driven LoRa/LoRaWAN sniff-and-inject radio.", }, // ---- software / projects ---- { slug: 'whad', name: 'WHAD', vendor: 'WHAD Team', type: 'software', protocols: ['BLE', 'Zigbee', 'Thread', '802.15.4', 'LoRaWAN', 'ESB'], repo: 'https://github.com/whad-team/whad-client', - note: "Wireless Hacking Devices — a unified Python framework and host protocol that drives many radios to sniff and inject across wireless stacks: BLE, IEEE 802.15.4 / Zigbee / RF4CE, Enhanced ShockBurst, Logitech Unifying, LoRaWAN and a generic PHY layer. Backends include the nRF52840 'Butterfly' firmware, an STM32WLxx (LoRa) firmware, ESP32, Ubertooth, APIMote, RZUSBstick, RFStorm/nRF24 and Yard Stick One, plus host HCI — one toolchain and PCAP/Scapy interface across protocols.", + note: "Wireless Hacking Devices, a unified Python framework and host protocol that drives many radios to sniff and inject across wireless stacks: BLE, IEEE 802.15.4 / Zigbee / RF4CE, Enhanced ShockBurst, Logitech Unifying, LoRaWAN and a generic PHY layer. Backends include the nRF52840 'Butterfly' firmware, an STM32WLxx (LoRa) firmware, ESP32, Ubertooth, APIMote, RZUSBstick, RFStorm/nRF24 and Yard Stick One, plus host HCI, one toolchain and PCAP/Scapy interface across protocols.", }, { slug: 'sniffle', name: 'Sniffle', vendor: 'NCC Group', type: 'software', protocols: ['BLE'], repo: 'https://github.com/nccgroup/Sniffle', - note: 'The reference modern open-source sniffer for Bluetooth 5 and 4.x LE on TI CC1352/CC26x2 (and CatSniffer). Python host, all BT5 PHYs, extended advertising, follows connections — the default LL-layer capture choice today.', + note: 'The reference modern open-source sniffer for Bluetooth 5 and 4.x LE on TI CC1352/CC26x2 (and CatSniffer). Python host, all BT5 PHYs, extended advertising, follows connections, the default LL-layer capture choice today.', }, { slug: 'ice9-bluetooth-sniffer', name: 'ice9-bluetooth-sniffer', vendor: 'ICE9 Consulting (Mike Ryan)', type: 'software', protocols: ['BLE', 'Bluetooth'], repo: 'https://github.com/mikeryan/ice9-bluetooth-sniffer', - note: 'SDR-based, Wireshark-compatible all-channel sniffer (HackRF / bladeRF / USRP). Unlike most sniffers it can sniff connections that are already established — invaluable when you cannot catch the connection request. Needs an SDR and GPU/CPU for channelisation.', + note: 'SDR-based, Wireshark-compatible all-channel sniffer (HackRF / bladeRF / USRP). Unlike most sniffers it can sniff connections that are already established, invaluable when you cannot catch the connection request. Needs an SDR and GPU/CPU for channelisation.', }, { slug: 'crackle', name: 'crackle', vendor: 'Mike Ryan', type: 'software', @@ -162,12 +162,12 @@ const tools = [ { slug: 'universal-radio-hacker', name: 'Universal Radio Hacker', vendor: 'open source', type: 'software', protocols: ['any SDR'], repo: 'https://github.com/jopohl/urh', - note: 'Integrated reversing workbench: auto-detect modulation/bitrate, extract bitstreams, diff captures and replay — the fastest path from raw I/Q to a labelled frame format.', + note: 'Integrated reversing workbench: auto-detect modulation/bitrate, extract bitstreams, diff captures and replay, the fastest path from raw I/Q to a labelled frame format.', }, { slug: 'wireshark', name: 'Wireshark', vendor: 'open source', type: 'software', protocols: ['any'], homepage: 'https://www.wireshark.org', - note: 'The universal packet dissector. Capture tools across these protocols export to PCAP, and Wireshark dissects, decodes and lets you filter the frames here — supplying a network/link key where one is needed to decrypt in place.', + note: 'The universal packet dissector. Capture tools across these protocols export to PCAP, and Wireshark dissects, decodes and lets you filter the frames here, supplying a network/link key where one is needed to decrypt in place.', }, { slug: 'aircrack-ng', name: 'aircrack-ng', vendor: 'open source', type: 'software', @@ -187,7 +187,7 @@ const tools = [ { slug: 'gqrx', name: 'Gqrx SDR', vendor: 'open source', type: 'software', protocols: ['any SDR'], repo: 'https://github.com/gqrx-sdr/gqrx', - note: 'Live spectrum + waterfall SDR receiver (HackRF, bladeRF, USRP…) — the quickest way to see what is transmitting and where, and to judge how much of the band a given radio covers.', + note: 'Live spectrum + waterfall SDR receiver (HackRF, bladeRF, USRP…), the quickest way to see what is transmitting and where, and to judge how much of the band a given radio covers.', }, { slug: 'ubertooth-tools', name: 'Ubertooth host tools', vendor: 'Great Scott Gadgets', type: 'software', @@ -204,17 +204,17 @@ const tools = [ { slug: 'hcxtools', name: 'hcxtools', vendor: 'ZerBea', type: 'software', protocols: ['Wi-Fi'], repo: 'https://github.com/ZerBea/hcxtools', - note: 'Companion converters for hcxdumptool captures. hcxpcapngtool turns a captured pcapng into the hashcat/John .hc22000 hash format — the bridge from a raw capture to an offline crack.', + note: 'Companion converters for hcxdumptool captures. hcxpcapngtool turns a captured pcapng into the hashcat/John .hc22000 hash format, the bridge from a raw capture to an offline crack.', }, { slug: 'hashcat', name: 'hashcat', vendor: 'hashcat', type: 'software', protocols: ['Wi-Fi'], repo: 'https://github.com/hashcat/hashcat', - note: 'GPU-accelerated password recovery. For Wi-Fi, mode 22000 cracks both WPA/WPA2 4-way handshakes and PMKIDs from a .hc22000 hash using dictionary, rule and mask attacks — the fastest offline WPA cracker.', + note: 'GPU-accelerated password recovery. For Wi-Fi, mode 22000 cracks both WPA/WPA2 4-way handshakes and PMKIDs from a .hc22000 hash using dictionary, rule and mask attacks, the fastest offline WPA cracker.', }, { slug: 'kismet', name: 'Kismet', vendor: 'Kismet Wireless', type: 'software', protocols: ['Wi-Fi', 'Zigbee', '802.15.4'], repo: 'https://github.com/kismetwireless/kismet', - note: 'Passive wireless detector, sniffer and wardriving tool. Channel-hops to log every AP, client and SSID (with GPS) and captures to pcapng without ever transmitting — the reference quiet survey/capture tool. Beyond Wi-Fi it has the widest 802.15.4/Zigbee datasource support of any tool here: a dedicated CatSniffer v3 Zigbee source (channels 12–26) plus nRF52840, CC2531, RZUSBstick, nRF51822 and NXP KW41Z (Kismet git / 2025-10+ releases).', + note: 'Passive wireless detector, sniffer and wardriving tool. Channel-hops to log every AP, client and SSID (with GPS) and captures to pcapng without ever transmitting, the reference quiet survey/capture tool. Beyond Wi-Fi it has the widest 802.15.4/Zigbee datasource support of any tool here: a dedicated CatSniffer v3 Zigbee source (channels 12 to 26) plus nRF52840, CC2531, RZUSBstick, nRF51822 and NXP KW41Z (Kismet git / 2025-10+ releases).', }, { slug: 'reaver', name: 'Reaver (t6x fork)', vendor: 't6x', type: 'software', @@ -224,7 +224,7 @@ const tools = [ { slug: 'mdk4', name: 'MDK4', vendor: 'aircrack-ng', type: 'software', protocols: ['Wi-Fi'], repo: 'https://github.com/aircrack-ng/mdk4', - note: '802.11 stress-testing and DoS toolkit: deauthentication floods, beacon floods (fake SSIDs), authentication floods, probe and other attacks — for testing how an AP and clients hold up under adversarial traffic.', + note: '802.11 stress-testing and DoS toolkit: deauthentication floods, beacon floods (fake SSIDs), authentication floods, probe and other attacks, for testing how an AP and clients hold up under adversarial traffic.', }, { slug: 'wifiphisher', name: 'Wifiphisher', vendor: 'Wifiphisher project', type: 'software', @@ -239,7 +239,7 @@ const tools = [ { slug: 'hostapd-mana', name: 'hostapd-mana', vendor: 'SensePost', type: 'software', protocols: ['Wi-Fi'], repo: 'https://github.com/sensepost/hostapd-mana', - note: "SensePost's modified hostapd for Wi-Fi attacks — the 'MANA' rogue AP that lures clients using their probe history and captures Enterprise/EAP credentials. The engine underneath EAPHammer.", + note: "SensePost's modified hostapd for Wi-Fi attacks, the 'MANA' rogue AP that lures clients using their probe history and captures Enterprise/EAP credentials. The engine underneath EAPHammer.", }, ]; diff --git a/src/content/tools/5greplay.md b/src/content/tools/5greplay.md index fb593fd..0b3fd55 100644 --- a/src/content/tools/5greplay.md +++ b/src/content/tools/5greplay.md @@ -10,8 +10,8 @@ homepage: 'https://5greplay.org' note: >- 5G network-traffic fuzzer and replay engine (built on Montimage's MMT). Takes captured 5G control-/data-plane traffic, lets you write rules to modify - fields, and replays the altered packets, online or offline, toward a target - 5G component (AMF/SMF over NGAP/SCTP, or a gNB) for protocol fuzzing and + fields, and replays the altered packets, online or offline, toward a target 5G + component (AMF/SMF over NGAP/SCTP, or a gNB) for protocol fuzzing and attack-injection testing. Operates on traffic, not radio: it consumes a capture (e.g. from Wireshark) and a target core, no SDR. --- diff --git a/src/content/tools/adsb-out.md b/src/content/tools/adsb-out.md index f742b4b..db395ef 100644 --- a/src/content/tools/adsb-out.md +++ b/src/content/tools/adsb-out.md @@ -10,10 +10,10 @@ note: >- A Python encoder that builds forged 1090ES ADS-B Extended Squitter frames (chosen ICAO address, position, altitude) into an I/Q sample file for transmission by a TX-capable SDR (HackRF via hackrf_transfer). The concrete - way to demonstrate ADS-B spoofing/injection, there is no authentication on - the link, so a higher-power forged frame is accepted as a real aircraft. - Author states it is for academic purposes only. AUTHORIZED, RF-CONTAINED - testing only: never radiate on-air, use a shielded enclosure or a conducted - (cabled) setup. Stable but inactive (last commit ~2021). + way to demonstrate ADS-B spoofing/injection, there is no authentication on the + link, so a higher-power forged frame is accepted as a real aircraft. Author + states it is for academic purposes only. AUTHORIZED, RF-CONTAINED testing + only: never radiate on-air, use a shielded enclosure or a conducted (cabled) + setup. Stable but inactive (last commit ~2021). --- A Python encoder that builds forged 1090ES ADS-B Extended Squitter frames (chosen ICAO address, position, altitude) into an I/Q sample file for transmission by a TX-capable SDR (HackRF via hackrf_transfer). The concrete way to demonstrate ADS-B spoofing/injection, there is no authentication on the link, so a higher-power forged frame is accepted as a real aircraft. Author states it is for academic purposes only. AUTHORIZED, RF-CONTAINED testing only: never radiate on-air, use a shielded enclosure or a conducted (cabled) setup. Stable but inactive (last commit ~2021). diff --git a/src/content/tools/chirpstack.md b/src/content/tools/chirpstack.md index f575b06..f939e53 100644 --- a/src/content/tools/chirpstack.md +++ b/src/content/tools/chirpstack.md @@ -11,8 +11,7 @@ repo: 'https://github.com/chirpstack/chirpstack' note: >- Open-source LoRaWAN Network Server stack (gateway bridge, network server, application server). Provides the network-server side a replay or fuzzing - attack is staged against, stand up a ChirpStack instance to model the - target's server and observe how it handles replayed, forged or malformed - frames. + attack is staged against, stand up a ChirpStack instance to model the target's + server and observe how it handles replayed, forged or malformed frames. --- Open-source LoRaWAN Network Server stack (gateway bridge, network server, application server). Provides the network-server side a replay or fuzzing attack is staged against, stand up a ChirpStack instance to model the target's server and observe how it handles replayed, forged or malformed frames. diff --git a/src/content/tools/cyd.md b/src/content/tools/cyd.md index 4ff1bf8..1195e7f 100644 --- a/src/content/tools/cyd.md +++ b/src/content/tools/cyd.md @@ -1,6 +1,6 @@ --- slug: cyd -name: CYD, Cheap Yellow Display (ESP32-2432S028R) +name: 'CYD, Cheap Yellow Display (ESP32-2432S028R)' vendor: community (Witnessmenow guide) type: hardware protocols: diff --git a/src/content/tools/dwm3000-dwt-driver.md b/src/content/tools/dwm3000-dwt-driver.md index 82fb2f7..6aa9563 100644 --- a/src/content/tools/dwm3000-dwt-driver.md +++ b/src/content/tools/dwm3000-dwt-driver.md @@ -11,7 +11,7 @@ note: >- dwt_uwb_driver API) to the DWS3000 Arduino shield, runnable under Zephyr. The practical glue for bringing up a DW3000 board, configuring its 802.15.4z PHY parameters (channel, preamble, PRF, STS mode), and running two-way-ranging - exchanges you can log, the dev-board path for capturing/characterising - ranging behaviour. A development driver, not an attack tool. + exchanges you can log, the dev-board path for capturing/characterising ranging + behaviour. A development driver, not an attack tool. --- An open port of Qorvo/Decawave's DWM3000 driver and ranging examples (the dwt_uwb_driver API) to the DWS3000 Arduino shield, runnable under Zephyr. The practical glue for bringing up a DW3000 board, configuring its 802.15.4z PHY parameters (channel, preamble, PRF, STS mode), and running two-way-ranging exchanges you can log, the dev-board path for capturing/characterising ranging behaviour. A development driver, not an attack tool. diff --git a/src/content/tools/dwm3000evb.md b/src/content/tools/dwm3000evb.md index 9a18268..706367e 100644 --- a/src/content/tools/dwm3000evb.md +++ b/src/content/tools/dwm3000evb.md @@ -18,7 +18,8 @@ note: >- second-generation impulse-radio transceiver) on an Arduino form factor. Designed against the FiRa PHY/MAC and interoperable with Apple's U1 & U2 chips, on channels 5 (6.5 GHz) and 9 (8 GHz). Drive it from a host MCU (e.g. a - NUCLEO-F429ZI or nRF52840) to range, log or, with the SEEMOO sniffer firmware, capture 802.15.4z frames. The same board (a ~$65 EVB + nRF52DK) was the - attack platform in the Ghost Peak research. + NUCLEO-F429ZI or nRF52840) to range, log or, with the SEEMOO sniffer firmware, + capture 802.15.4z frames. The same board (a ~$65 EVB + nRF52DK) was the attack + platform in the Ghost Peak research. --- The reference DW3000-family UWB development shield: a DWM3000 module (DW3110 second-generation impulse-radio transceiver) on an Arduino form factor. Designed against the FiRa PHY/MAC and interoperable with Apple's U1 & U2 chips, on channels 5 (6.5 GHz) and 9 (8 GHz). Drive it from a host MCU (e.g. a NUCLEO-F429ZI or nRF52840) to range, log or, with the SEEMOO sniffer firmware, capture 802.15.4z frames. The same board (a ~$65 EVB + nRF52DK) was the attack platform in the Ghost Peak research. diff --git a/src/content/tools/esp32-bt-classic-sniffer.md b/src/content/tools/esp32-bt-classic-sniffer.md index 7f0615f..58841f8 100644 --- a/src/content/tools/esp32-bt-classic-sniffer.md +++ b/src/content/tools/esp32-bt-classic-sniffer.md @@ -7,11 +7,11 @@ protocols: - Bluetooth Classic repo: 'https://github.com/Matheus-Garbelini/esp32_bluetooth_classic_sniffer' note: >- - The reference active BR/EDR sniffer on commodity ESP32 hardware (~$4 to 10; ~590 - stars, GPL-2.0). It patches the ESP32 ROM Bluetooth stack to dump baseband - packets, BT header, channel, device role, FHS, ACL and LMP, over USB serial - to a host Python tool (BTSnifferBREDR.py) with Scapy/Wireshark output. This is - Bluetooth CLASSIC (BR/EDR), not BLE. It actively connects to the target, so - authorised testing only. + The reference active BR/EDR sniffer on commodity ESP32 hardware (~$4 to 10; + ~590 stars, GPL-2.0). It patches the ESP32 ROM Bluetooth stack to dump + baseband packets, BT header, channel, device role, FHS, ACL and LMP, over USB + serial to a host Python tool (BTSnifferBREDR.py) with Scapy/Wireshark output. + This is Bluetooth CLASSIC (BR/EDR), not BLE. It actively connects to the + target, so authorised testing only. --- The reference active BR/EDR sniffer on commodity ESP32 hardware (~$4 to 10; ~590 stars, GPL-2.0). It patches the ESP32 ROM Bluetooth stack to dump baseband packets, BT header, channel, device role, FHS, ACL and LMP, over USB serial to a host Python tool (BTSnifferBREDR.py) with Scapy/Wireshark output. This is Bluetooth CLASSIC (BR/EDR), not BLE. It actively connects to the target, so authorised testing only. diff --git a/src/content/tools/esp32-bt-exp.md b/src/content/tools/esp32-bt-exp.md index aa60c9f..5d1f8e0 100644 --- a/src/content/tools/esp32-bt-exp.md +++ b/src/content/tools/esp32-bt-exp.md @@ -10,7 +10,7 @@ repo: 'https://github.com/esp32beans/ESP32-BT-exp' note: >- An Arduino-ESP32 sketch that brings up the Bluedroid stack in dual-mode (Classic + BLE) and dumps discovered devices in pairing/inquiry mode (MIT). - Discovery only, no pairing or connection. Classic (BR/EDR) discovery needs - the original ESP32, not the C-series, which has no Bluetooth Classic radio. + Discovery only, no pairing or connection. Classic (BR/EDR) discovery needs the + original ESP32, not the C-series, which has no Bluetooth Classic radio. --- An Arduino-ESP32 sketch that brings up the Bluedroid stack in dual-mode (Classic + BLE) and dumps discovered devices in pairing/inquiry mode (MIT). Discovery only, no pairing or connection. Classic (BR/EDR) discovery needs the original ESP32, not the C-series, which has no Bluetooth Classic radio. diff --git a/src/content/tools/esp32-classic-bt-scan.md b/src/content/tools/esp32-classic-bt-scan.md index 5b0292f..b7ffe52 100644 --- a/src/content/tools/esp32-classic-bt-scan.md +++ b/src/content/tools/esp32-classic-bt-scan.md @@ -8,9 +8,9 @@ protocols: repo: 'https://github.com/AntorFr/ClassicBTScan' note: >- A small Arduino-ESP32 library that performs a true Bluetooth Classic (BR/EDR) - inquiry scan via the Bluedroid GAP API, returning each discovered device's - MAC address, name, RSSI and Class-of-Device (CoD). The BR/EDR analogue of a - BLE advertising scan (MIT, last push 2020). Only finds devices in discoverable - / inquiry-scan mode; pin it to a known ESP-IDF as it is unmaintained. + inquiry scan via the Bluedroid GAP API, returning each discovered device's MAC + address, name, RSSI and Class-of-Device (CoD). The BR/EDR analogue of a BLE + advertising scan (MIT, last push 2020). Only finds devices in discoverable / + inquiry-scan mode; pin it to a known ESP-IDF as it is unmaintained. --- A small Arduino-ESP32 library that performs a true Bluetooth Classic (BR/EDR) inquiry scan via the Bluedroid GAP API, returning each discovered device's MAC address, name, RSSI and Class-of-Device (CoD). The BR/EDR analogue of a BLE advertising scan (MIT, last push 2020). Only finds devices in discoverable / inquiry-scan mode; pin it to a known ESP-IDF as it is unmaintained. diff --git a/src/content/tools/esp32-sour-apple.md b/src/content/tools/esp32-sour-apple.md index f2d4a55..02625d7 100644 --- a/src/content/tools/esp32-sour-apple.md +++ b/src/content/tools/esp32-sour-apple.md @@ -10,7 +10,7 @@ note: >- A focused PoC that crashes/freezes iOS devices by flooding them with BLE pairing-request advertisements (~595 stars, GPL-3.0). Tested on ESP32-S3 and ESP-WROOM-32 (an ESP8266 cannot run it, no BLE radio). Genuinely disruptive, - it can freeze nearby iPhones, so authorised testing only, on hardware you - own. Target/payload effectiveness dates as Apple patches. + it can freeze nearby iPhones, so authorised testing only, on hardware you own. + Target/payload effectiveness dates as Apple patches. --- A focused PoC that crashes/freezes iOS devices by flooding them with BLE pairing-request advertisements (~595 stars, GPL-3.0). Tested on ESP32-S3 and ESP-WROOM-32 (an ESP8266 cannot run it, no BLE radio). Genuinely disruptive, it can freeze nearby iPhones, so authorised testing only, on hardware you own. Target/payload effectiveness dates as Apple patches. diff --git a/src/content/tools/evilapplejuice-esp32.md b/src/content/tools/evilapplejuice-esp32.md index 19995e5..34d1ffb 100644 --- a/src/content/tools/evilapplejuice-esp32.md +++ b/src/content/tools/evilapplejuice-esp32.md @@ -7,7 +7,8 @@ protocols: - BLE repo: 'https://github.com/ckcr4lyf/EvilAppleJuice-ESP32' note: >- - A self-contained ESP32 sketch that spams Apple BLE proximity-pairing messages, the 'connect AirPods / setup' style popups, on nearby iOS devices (~2.1k + A self-contained ESP32 sketch that spams Apple BLE proximity-pairing messages, + the 'connect AirPods / setup' style popups, on nearby iOS devices (~2.1k stars). Single-purpose Apple advertising spam, derived from the AppleJuice proximity-spoof research. Authorised testing only; disruptive to all nearby Apple devices. diff --git a/src/content/tools/ez-wave.md b/src/content/tools/ez-wave.md index 041074e..7b7d433 100644 --- a/src/content/tools/ez-wave.md +++ b/src/content/tools/ez-wave.md @@ -13,7 +13,7 @@ note: >- interrogates a device (manufacturer/model, firmware version, supported command classes, configuration), and ezfingerprint identifies the Z-Wave module generation via a PHY preamble-length manipulation. Default config drives two - HackRF One SDRs. Python 2.7 / GNU Radio 3.7 era, dated but still the - canonical exploitation toolkit. + HackRF One SDRs. Python 2.7 / GNU Radio 3.7 era, dated but still the canonical + exploitation toolkit. --- The reference open Z-Wave assessment suite (GNU Radio + Scapy-radio): ezstumbler does passive discovery and active network enumeration, ezrecon interrogates a device (manufacturer/model, firmware version, supported command classes, configuration), and ezfingerprint identifies the Z-Wave module generation via a PHY preamble-length manipulation. Default config drives two HackRF One SDRs. Python 2.7 / GNU Radio 3.7 era, dated but still the canonical exploitation toolkit. diff --git a/src/content/tools/flipper-wifi-devboard.md b/src/content/tools/flipper-wifi-devboard.md index f0cdacb..9893e6d 100644 --- a/src/content/tools/flipper-wifi-devboard.md +++ b/src/content/tools/flipper-wifi-devboard.md @@ -5,7 +5,7 @@ vendor: Flipper Devices type: hardware protocols: - Wi-Fi -spec: ESP32-S2-WROVER · 2.4 GHz Wi-Fi only, S2 has NO Bluetooth radio +spec: 'ESP32-S2-WROVER · 2.4 GHz Wi-Fi only, S2 has NO Bluetooth radio' homepage: 'https://flipper.net/products/wifi-devboard' software: - esp32-marauder diff --git a/src/content/tools/flipper-zero.md b/src/content/tools/flipper-zero.md index 2b29d97..0270296 100644 --- a/src/content/tools/flipper-zero.md +++ b/src/content/tools/flipper-zero.md @@ -9,16 +9,17 @@ protocols: - NFC - Infrared spec: >- - CC1101 transceiver · RX/TX 300 to 348, 387 to 464 & 779 to 928 MHz · OOK/ASK + (G)FSK · - handheld + CC1101 transceiver · RX/TX 300 to 348, 387 to 464 & 779 to 928 MHz · OOK/ASK + + (G)FSK · handheld homepage: 'https://flipper.net/' software: - flipperzero-firmware note: >- Handheld multitool whose built-in CC1101 transceiver receives and transmits - across the 300 to 348, 387 to 464 and 779 to 928 MHz sub-GHz bands, the everyday field - radio for reading, saving and replaying garage/gate/doorbell remotes and other - fixed-code devices, with no laptop or SDR. OOK/ASK and (G)FSK; its Read mode - decodes known protocols and Read RAW captures unknown ones for later replay. + across the 300 to 348, 387 to 464 and 779 to 928 MHz sub-GHz bands, the + everyday field radio for reading, saving and replaying garage/gate/doorbell + remotes and other fixed-code devices, with no laptop or SDR. OOK/ASK and + (G)FSK; its Read mode decodes known protocols and Read RAW captures unknown + ones for later replay. --- Handheld multitool whose built-in CC1101 transceiver receives and transmits across the 300 to 348, 387 to 464 and 779 to 928 MHz sub-GHz bands, the everyday field radio for reading, saving and replaying garage/gate/doorbell remotes and other fixed-code devices, with no laptop or SDR. OOK/ASK and (G)FSK; its Read mode decodes known protocols and Read RAW captures unknown ones for later replay. diff --git a/src/content/tools/gps-sdr-sim.md b/src/content/tools/gps-sdr-sim.md index 443fca0..2a6bbb0 100644 --- a/src/content/tools/gps-sdr-sim.md +++ b/src/content/tools/gps-sdr-sim.md @@ -13,7 +13,7 @@ note: >- replayed/synthesised signal at higher power can pull a receiver's position and clock to attacker-chosen values, the canonical GPS spoofing tool. AUTHORIZED, RF-CONTAINED testing only: transmitting GPS over the air is illegal in most - jurisdictions, use a shielded enclosure or a cabled (conducted) setup. Repo - is archived but remains the de-facto reference. + jurisdictions, use a shielded enclosure or a cabled (conducted) setup. Repo is + archived but remains the de-facto reference. --- Generates a GPS L1 C/A baseband I/Q file from a RINEX broadcast ephemeris and a chosen static or moving position, for transmission by an SDR (HackRF / bladeRF / USRP). Because civilian C/A is unauthenticated, a replayed/synthesised signal at higher power can pull a receiver's position and clock to attacker-chosen values, the canonical GPS spoofing tool. AUTHORIZED, RF-CONTAINED testing only: transmitting GPS over the air is illegal in most jurisdictions, use a shielded enclosure or a cabled (conducted) setup. Repo is archived but remains the de-facto reference. diff --git a/src/content/tools/gpsd.md b/src/content/tools/gpsd.md index f2e0a6a..690bab7 100644 --- a/src/content/tools/gpsd.md +++ b/src/content/tools/gpsd.md @@ -10,10 +10,9 @@ homepage: 'https://gpsd.io/' note: >- The GPS service daemon: it reads the NMEA 0183 / UBX stream from a GNSS receiver on a serial or USB port, parses it, and re-serves the solved - position/velocity/time to clients over a simple TCP/JSON protocol, with - gpsmon and cgps for live terminal display of the fix, satellites and raw - sentences. The standard way to consume a real GPS receiver on Linux/BSD and - the normal 'see what the receiver reports' tool. Hosted on GitLab/Savannah, - not GitHub. + position/velocity/time to clients over a simple TCP/JSON protocol, with gpsmon + and cgps for live terminal display of the fix, satellites and raw sentences. + The standard way to consume a real GPS receiver on Linux/BSD and the normal + 'see what the receiver reports' tool. Hosted on GitLab/Savannah, not GitHub. --- The GPS service daemon: it reads the NMEA 0183 / UBX stream from a GNSS receiver on a serial or USB port, parses it, and re-serves the solved position/velocity/time to clients over a simple TCP/JSON protocol, with gpsmon and cgps for live terminal display of the fix, satellites and raw sentences. The standard way to consume a real GPS receiver on Linux/BSD and the normal 'see what the receiver reports' tool. Hosted on GitLab/Savannah, not GitHub. diff --git a/src/content/tools/hackrf-one.md b/src/content/tools/hackrf-one.md index 9bf0ffa..c3ffc27 100644 --- a/src/content/tools/hackrf-one.md +++ b/src/content/tools/hackrf-one.md @@ -11,8 +11,8 @@ software: - universal-radio-hacker - ice9-bluetooth-sniffer note: >- - 1 MHz to 6 GHz half-duplex SDR, the discovery radio for 'Rapid Radio Reversing': - find and characterise an unknown signal before working it with a narrowband - tool. + 1 MHz to 6 GHz half-duplex SDR, the discovery radio for 'Rapid Radio + Reversing': find and characterise an unknown signal before working it with a + narrowband tool. --- 1 MHz to 6 GHz half-duplex SDR, the discovery radio for 'Rapid Radio Reversing': find and characterise an unknown signal before working it with a narrowband tool. diff --git a/src/content/tools/hostapd-mana.md b/src/content/tools/hostapd-mana.md index 27a7c2c..d4df9b0 100644 --- a/src/content/tools/hostapd-mana.md +++ b/src/content/tools/hostapd-mana.md @@ -7,8 +7,8 @@ protocols: - Wi-Fi repo: 'https://github.com/sensepost/hostapd-mana' note: >- - SensePost's modified hostapd for Wi-Fi attacks, the 'MANA' rogue AP that - lures clients using their probe history and captures Enterprise/EAP - credentials. The engine underneath EAPHammer. + SensePost's modified hostapd for Wi-Fi attacks, the 'MANA' rogue AP that lures + clients using their probe history and captures Enterprise/EAP credentials. The + engine underneath EAPHammer. --- SensePost's modified hostapd for Wi-Fi attacks, the 'MANA' rogue AP that lures clients using their probe history and captures Enterprise/EAP credentials. The engine underneath EAPHammer. diff --git a/src/content/tools/kismet.md b/src/content/tools/kismet.md index c3049b0..eda399c 100644 --- a/src/content/tools/kismet.md +++ b/src/content/tools/kismet.md @@ -11,8 +11,8 @@ repo: 'https://github.com/kismetwireless/kismet' note: >- Passive wireless detector, sniffer and wardriving tool. Channel-hops to log every AP, client and SSID (with GPS) and captures to pcapng without ever - transmitting, the reference quiet survey/capture tool. Beyond Wi-Fi it has - the widest 802.15.4/Zigbee datasource support of any tool here: a dedicated + transmitting, the reference quiet survey/capture tool. Beyond Wi-Fi it has the + widest 802.15.4/Zigbee datasource support of any tool here: a dedicated CatSniffer v3 Zigbee source (channels 12 to 26) plus nRF52840, CC2531, RZUSBstick, nRF51822 and NXP KW41Z (Kismet git / 2025-10+ releases). --- diff --git a/src/content/tools/libnfc.md b/src/content/tools/libnfc.md index 3d0d639..2c7a08e 100644 --- a/src/content/tools/libnfc.md +++ b/src/content/tools/libnfc.md @@ -9,6 +9,7 @@ protocols: repo: 'https://github.com/nfc-tools/libnfc' note: >- Platform-independent NFC library and tools (nfc-list, nfc-mfclassic) that - drive PN532/ACR122U-class HF readers to read and dump ISO 14443-A MIFARE cards, and the host stack the mfoc and mfcuk Crypto1 crackers build on. + drive PN532/ACR122U-class HF readers to read and dump ISO 14443-A MIFARE + cards, and the host stack the mfoc and mfcuk Crypto1 crackers build on. --- Platform-independent NFC library and tools (nfc-list, nfc-mfclassic) that drive PN532/ACR122U-class HF readers to read and dump ISO 14443-A MIFARE cards, and the host stack the mfoc and mfcuk Crypto1 crackers build on. diff --git a/src/content/tools/matter-dcl.md b/src/content/tools/matter-dcl.md index 78c6c74..d40e8f9 100644 --- a/src/content/tools/matter-dcl.md +++ b/src/content/tools/matter-dcl.md @@ -15,7 +15,7 @@ note: >- certification status, and the Product Attestation Authority (PAA) root certificates that commissioners trust for device attestation. At Identify, the DCL turns the VID/PID read off a device's onboarding payload into a known - vendor/product and certification record, and a Test-Vendor VID - (0xFFF1 to 0xFFF4) on a 'production' device is an immediate red flag. + vendor/product and certification record, and a Test-Vendor VID (0xFFF1 to + 0xFFF4) on a 'production' device is an immediate red flag. --- The CSA-run public ledger (Cosmos SDK / CometBFT) of Matter device data: vendor and product info keyed by Vendor ID (VID) and Product ID (PID), certification status, and the Product Attestation Authority (PAA) root certificates that commissioners trust for device attestation. At Identify, the DCL turns the VID/PID read off a device's onboarding payload into a known vendor/product and certification record, and a Test-Vendor VID (0xFFF1 to 0xFFF4) on a 'production' device is an immediate red flag. diff --git a/src/content/tools/murata-type2bp.md b/src/content/tools/murata-type2bp.md index 53268e7..1923254 100644 --- a/src/content/tools/murata-type2bp.md +++ b/src/content/tools/murata-type2bp.md @@ -10,11 +10,13 @@ spec: >- NXP Trimension SR150 chipset · FiRa Certified · UWB ch 5 / ch 9 (6.25 to 8.25 GHz) · two-way ranging + 2D/3D Angle-of-Arrival (up to 3 antennas) · SPI note: >- - A compact production UWB module built on NXP's Trimension SR150 (not a DW3000), included here because the NXP UWB silicon family is the other half of the - deployed ecosystem (NXP chips feature in car digital-key and phone designs, - and inter-operate with Apple U1 in the Ghost Peak results). FiRa Certified, - supports two-way ranging and 2D/3D Angle-of-Arrival with up to three antennas. - A module for building/representing an NXP-based ranging peer; identify it by - its SR150 silicon rather than assuming every UWB target is a Qorvo DW3000. + A compact production UWB module built on NXP's Trimension SR150 (not a + DW3000), included here because the NXP UWB silicon family is the other half of + the deployed ecosystem (NXP chips feature in car digital-key and phone + designs, and inter-operate with Apple U1 in the Ghost Peak results). FiRa + Certified, supports two-way ranging and 2D/3D Angle-of-Arrival with up to + three antennas. A module for building/representing an NXP-based ranging peer; + identify it by its SR150 silicon rather than assuming every UWB target is a + Qorvo DW3000. --- A compact production UWB module built on NXP's Trimension SR150 (not a DW3000), included here because the NXP UWB silicon family is the other half of the deployed ecosystem (NXP chips feature in car digital-key and phone designs, and inter-operate with Apple U1 in the Ghost Peak results). FiRa Certified, supports two-way ranging and 2D/3D Angle-of-Arrival with up to three antennas. A module for building/representing an NXP-based ranging peer; identify it by its SR150 silicon rather than assuming every UWB target is a Qorvo DW3000. diff --git a/src/content/tools/openairinterface5g.md b/src/content/tools/openairinterface5g.md index 94279aa..699663b 100644 --- a/src/content/tools/openairinterface5g.md +++ b/src/content/tools/openairinterface5g.md @@ -9,8 +9,8 @@ repo: 'https://github.com/openairinterface/openairinterface5g' homepage: 'https://openairinterface.org' note: >- Full open-source LTE/NR RAN and core reference stack (eNodeB/gNB, UE and EPC). - A second independent platform, alongside srsRAN, for standing up a - test/rogue eNodeB on a TX-capable SDR and for RRC/NAS signalling experiments - and protocol fuzzing in an authorised lab. + A second independent platform, alongside srsRAN, for standing up a test/rogue + eNodeB on a TX-capable SDR and for RRC/NAS signalling experiments and protocol + fuzzing in an authorised lab. --- Full open-source LTE/NR RAN and core reference stack (eNodeB/gNB, UE and EPC). A second independent platform, alongside srsRAN, for standing up a test/rogue eNodeB on a TX-capable SDR and for RRC/NAS signalling experiments and protocol fuzzing in an authorised lab. diff --git a/src/content/tools/pymodes.md b/src/content/tools/pymodes.md index b0394de..457ca52 100644 --- a/src/content/tools/pymodes.md +++ b/src/content/tools/pymodes.md @@ -10,8 +10,8 @@ note: >- A pure-Python decoder library for Mode S and ADS-B messages: feed it hex frames (or stream them from dump1090 over TCP/Beast) and it returns the decoded fields, ICAO address, callsign, airborne/surface position (CPR), - velocity, altitude, plus DF4/5/11/20/21 surveillance and Comm-B BDS - registers. The reference way to interpret message contents and to run - plausibility / anti-spoof checks on a decoded feed in your own code. + velocity, altitude, plus DF4/5/11/20/21 surveillance and Comm-B BDS registers. + The reference way to interpret message contents and to run plausibility / + anti-spoof checks on a decoded feed in your own code. --- A pure-Python decoder library for Mode S and ADS-B messages: feed it hex frames (or stream them from dump1090 over TCP/Beast) and it returns the decoded fields, ICAO address, callsign, airborne/surface position (CPR), velocity, altitude, plus DF4/5/11/20/21 surveillance and Comm-B BDS registers. The reference way to interpret message contents and to run plausibility / anti-spoof checks on a decoded feed in your own code. diff --git a/src/content/tools/python-matter-server.md b/src/content/tools/python-matter-server.md index 4bcd372..67e6986 100644 --- a/src/content/tools/python-matter-server.md +++ b/src/content/tools/python-matter-server.md @@ -12,8 +12,8 @@ note: >- A CSA-certified Matter Controller Server (the one behind Home Assistant's Matter integration) that wraps the CHIP SDK and exposes commissioning and the operational cluster model over a WebSocket API. Acts as a standing - controller/commissioner you can drive programmatically, commission a node - over BLE, then enumerate and exercise its clusters. Maintenance mode (being - rebuilt on matter.js), but a real, working Matter controller. + controller/commissioner you can drive programmatically, commission a node over + BLE, then enumerate and exercise its clusters. Maintenance mode (being rebuilt + on matter.js), but a real, working Matter controller. --- A CSA-certified Matter Controller Server (the one behind Home Assistant's Matter integration) that wraps the CHIP SDK and exposes commissioning and the operational cluster model over a WebSocket API. Acts as a standing controller/commissioner you can drive programmatically, commission a node over BLE, then enumerate and exercise its clusters. Maintenance mode (being rebuilt on matter.js), but a real, working Matter controller. diff --git a/src/content/tools/qcsuper.md b/src/content/tools/qcsuper.md index cc6174e..aa197be 100644 --- a/src/content/tools/qcsuper.md +++ b/src/content/tools/qcsuper.md @@ -11,7 +11,7 @@ note: >- Captures raw 2G/3G/4G (and, on some modems, 5G) radio frames from Qualcomm-based phones and modems via the /dev/diag DIAG interface, wraps them in GSMTAP and streams a live PCAP into Wireshark. Turns a cheap Qualcomm modem - such as the SIM7600 into a passive cellular-signalling sniffer, an - alternative to an SDR cell-search receiver. + such as the SIM7600 into a passive cellular-signalling sniffer, an alternative + to an SDR cell-search receiver. --- Captures raw 2G/3G/4G (and, on some modems, 5G) radio frames from Qualcomm-based phones and modems via the /dev/diag DIAG interface, wraps them in GSMTAP and streams a live PCAP into Wireshark. Turns a cheap Qualcomm modem such as the SIM7600 into a passive cellular-signalling sniffer, an alternative to an SDR cell-search receiver. diff --git a/src/content/tools/rak-wisgate-connect.md b/src/content/tools/rak-wisgate-connect.md index 3bfd4a5..6a721c4 100644 --- a/src/content/tools/rak-wisgate-connect.md +++ b/src/content/tools/rak-wisgate-connect.md @@ -13,7 +13,7 @@ software: note: >- RAKwireless multi-channel LoRaWAN gateway built on a Raspberry Pi CM4 with an SX1302/SX1303 concentrator. Receives every LoRaWAN channel at once and feeds - frames over the Semtech UDP packet forwarder, the gateway ChirpCat is - designed to run on for uplink/downlink capture. + frames over the Semtech UDP packet forwarder, the gateway ChirpCat is designed + to run on for uplink/downlink capture. --- RAKwireless multi-channel LoRaWAN gateway built on a Raspberry Pi CM4 with an SX1302/SX1303 concentrator. Receives every LoRaWAN channel at once and feeds frames over the Semtech UDP packet forwarder, the gateway ChirpCat is designed to run on for uplink/downlink capture. diff --git a/src/content/tools/silabs-uzb7.md b/src/content/tools/silabs-uzb7.md index 8442522..7a65f81 100644 --- a/src/content/tools/silabs-uzb7.md +++ b/src/content/tools/silabs-uzb7.md @@ -14,8 +14,9 @@ software: - zwave-pc-controller - zwave-zniffer note: >- - Silicon Labs' EFR32ZG14 USB stick that exposes the Z-Wave Serial API to a host, the controller adapter the Z-Wave PC Controller drives, and (re-flashed with - Zniffer firmware) the capture adapter for the Z-Wave Zniffer. The official - native-radio hardware for both vendor tools, ~US$21. + Silicon Labs' EFR32ZG14 USB stick that exposes the Z-Wave Serial API to a + host, the controller adapter the Z-Wave PC Controller drives, and (re-flashed + with Zniffer firmware) the capture adapter for the Z-Wave Zniffer. The + official native-radio hardware for both vendor tools, ~US$21. --- Silicon Labs' EFR32ZG14 USB stick that exposes the Z-Wave Serial API to a host, the controller adapter the Z-Wave PC Controller drives, and (re-flashed with Zniffer firmware) the capture adapter for the Z-Wave Zniffer. The official native-radio hardware for both vendor tools, ~US$21. diff --git a/src/content/tools/yard-stick-one.md b/src/content/tools/yard-stick-one.md index 859ad00..f04e1b6 100644 --- a/src/content/tools/yard-stick-one.md +++ b/src/content/tools/yard-stick-one.md @@ -10,8 +10,8 @@ software: - rfcat - universal-radio-hacker note: >- - CC1111 sub-GHz transceiver (300 to 928 MHz) driven by rfcat, receive, replay and - transmit OOK/ASK/FSK from a Python shell. The reference cheap Sub-GHz work + CC1111 sub-GHz transceiver (300 to 928 MHz) driven by rfcat, receive, replay + and transmit OOK/ASK/FSK from a Python shell. The reference cheap Sub-GHz work tool, paired with a HackRF for discovery. --- CC1111 sub-GHz transceiver (300 to 928 MHz) driven by rfcat, receive, replay and transmit OOK/ASK/FSK from a Python shell. The reference cheap Sub-GHz work tool, paired with a HackRF for discovery. From 07b358a7aa60d46c16149610accde27fd8bb92fc Mon Sep 17 00:00:00 2001 From: Eduardo Contreras Date: Mon, 28 Sep 2026 17:05:09 -0600 Subject: [PATCH 5/5] Remove dashes from the toolchains and data files --- .gitignore | 4 +- src/data/bsamRelation.js | 4 +- src/data/meta.js | 4 +- src/data/protocols.js | 6 +- src/data/toolchains.js | 114 +++++++++++++++---------------- src/data/toolchains/adsb.js | 38 +++++------ src/data/toolchains/btclassic.js | 44 ++++++------ src/data/toolchains/gnss.js | 38 +++++------ src/data/toolchains/gsm.js | 34 ++++----- src/data/toolchains/lora.js | 56 +++++++-------- src/data/toolchains/lte.js | 60 ++++++++-------- src/data/toolchains/nr5g.js | 62 ++++++++--------- src/data/toolchains/rfid.js | 52 +++++++------- src/data/toolchains/subg.js | 62 ++++++++--------- src/data/toolchains/thread.js | 62 ++++++++--------- src/data/toolchains/uwb.js | 40 +++++------ src/data/toolchains/zigbee.js | 60 ++++++++-------- src/data/toolchains/zwave.js | 56 +++++++-------- src/lib/taxonomy.js | 2 +- 19 files changed, 399 insertions(+), 399 deletions(-) diff --git a/.gitignore b/.gitignore index 32bb73a..9992ecb 100644 --- a/.gitignore +++ b/.gitignore @@ -7,9 +7,9 @@ dist/ .env.* __pycache__/ -# Internal working docs — never published +# Internal working docs, never published docs/ /.atl -# RFSAM Skill — audit artifacts and secrets, never committed +# RFSAM Skill, audit artifacts and secrets, never committed Skill/loot/ diff --git a/src/data/bsamRelation.js b/src/data/bsamRelation.js index bc8871c..249cb9e 100644 --- a/src/data/bsamRelation.js +++ b/src/data/bsamRelation.js @@ -1,5 +1,5 @@ export const bsamRelation = { - "summary": "RFSAM is complementary to Tarlogic's BSAM, not a replacement. BSAM is an excellent, mature methodology for Bluetooth — but it begins at the link layer and is Bluetooth-only. RFSAM owns the two floors below that (Spectrum and Signal/PHY) for every protocol, and extends to LoRa/LoRaWAN and LTE which BSAM does not cover. For Bluetooth at the link layer and above — discovery data, pairing, authentication, encryption, services, application — RFSAM defers to BSAM: its RFSAM-BLE controls at those layers describe only the RF-capture prerequisite needed to reach the point where the corresponding BSAM control applies, then cite it directly.", + "summary": "RFSAM is complementary to Tarlogic's BSAM, not a replacement. BSAM is an excellent, mature methodology for Bluetooth, but it begins at the link layer and is Bluetooth-only. RFSAM owns the two floors below that (Spectrum and Signal/PHY) for every protocol, and extends to LoRa/LoRaWAN and LTE which BSAM does not cover. For Bluetooth at the link layer and above, discovery data, pairing, authentication, encryption, services, application, RFSAM defers to BSAM: its RFSAM-BLE controls at those layers describe only the RF-capture prerequisite needed to reach the point where the corresponding BSAM control applies, then cite it directly.", "ownership": [ { "rfsam": "Spectrum (SP) + Signal/PHY", @@ -14,6 +14,6 @@ export const bsamRelation = { "note": "RFSAM-owned end to end. BSAM is Bluetooth-only." } ], - "priorArt": "RFSAM isn't a claim to have invented RF security — OSSTMM defines a spectrum-security channel, BSAM (Tarlogic) is the mature Bluetooth reference, the SDR-pentest lineage (Ossmann, Black Hat 2008; Picod et al., Black Hat 2014) built the practical tooling, and a deep body of academic RF threat taxonomies exists. What's missing is a single oriented reference that ties that landscape together into something a practitioner can navigate by, end to end, across protocols. RFSAM's purpose is to be that north: structured, numbered controls with real commands and worked examples, so someone facing an unknown signal has a place to start and a way to know what they've covered.", + "priorArt": "RFSAM isn't a claim to have invented RF security, OSSTMM defines a spectrum-security channel, BSAM (Tarlogic) is the mature Bluetooth reference, the SDR-pentest lineage (Ossmann, Black Hat 2008; Picod et al., Black Hat 2014) built the practical tooling, and a deep body of academic RF threat taxonomies exists. What's missing is a single oriented reference that ties that landscape together into something a practitioner can navigate by, end to end, across protocols. RFSAM's purpose is to be that north: structured, numbered controls with real commands and worked examples, so someone facing an unknown signal has a place to start and a way to know what they've covered.", "url": "https://www.tarlogic.com/bsam/" }; diff --git a/src/data/meta.js b/src/data/meta.js index a622290..ff9fa64 100644 --- a/src/data/meta.js +++ b/src/data/meta.js @@ -2,6 +2,6 @@ export const meta = { "title": "RFSAM", "subtitle": "Radio Frequency Security Assessment Methodology", "org": "Electronic Cats", - "version": "0.1 — draft", - "blurb": "RF research and auditing have plenty of tools and scattered knowledge, but no single map. Faced with an unknown signal or device, where do you start — and how do you know what you've missed? RFSAM is meant to be that north: an open, structured reference that walks you from the spectrum up through the signal, link, crypto, attack and application layers, per protocol, with a verification procedure and a real worked example at each step. It doesn't claim to invent RF security — OSSTMM, BSAM and a deep body of research came first. It aims to organise that landscape into something you can navigate by, whether you're auditing a device or learning the field." + "version": "0.1, draft", + "blurb": "RF research and auditing have plenty of tools and scattered knowledge, but no single map. Faced with an unknown signal or device, where do you start, and how do you know what you've missed? RFSAM is meant to be that north: an open, structured reference that walks you from the spectrum up through the signal, link, crypto, attack and application layers, per protocol, with a verification procedure and a real worked example at each step. It doesn't claim to invent RF security, OSSTMM, BSAM and a deep body of research came first. It aims to organise that landscape into something you can navigate by, whether you're auditing a device or learning the field." }; diff --git a/src/data/protocols.js b/src/data/protocols.js index 8b23542..a7cf55d 100644 --- a/src/data/protocols.js +++ b/src/data/protocols.js @@ -1,8 +1,8 @@ // Each protocol: id (matches the ID segment), name, band, prefix, status. // `status: 'deepen'` = exists in the legacy corpus; `status: 'new'` = added for the full map. export const protocols = [ - { id: 'BLE', name: 'Bluetooth Low Energy', band: '2.400–2.480 GHz', prefix: 'RFSAM-BLE', status: 'deepen' }, - { id: 'BTC', name: 'Bluetooth Classic', band: '2.402–2.480 GHz (BR/EDR)', prefix: 'RFSAM-BTC', status: 'new' }, + { id: 'BLE', name: 'Bluetooth Low Energy', band: '2.400 to 2.480 GHz', prefix: 'RFSAM-BLE', status: 'deepen' }, + { id: 'BTC', name: 'Bluetooth Classic', band: '2.402 to 2.480 GHz (BR/EDR)', prefix: 'RFSAM-BTC', status: 'new' }, { id: 'WIFI', name: 'Wi-Fi (802.11)', band: '2.4 / 5 / 6 GHz', prefix: 'RFSAM-WIFI', status: 'deepen' }, { id: 'LORA', name: 'LoRa / LoRaWAN', band: 'ISM sub-GHz (US915 / EU868)', prefix: 'RFSAM-LORA', status: 'deepen' }, { id: 'LTE', name: 'LTE / 4G', band: 'Licensed cellular', prefix: 'RFSAM-LTE', status: 'deepen' }, @@ -15,5 +15,5 @@ export const protocols = [ { id: 'ADSB', name: 'ADS-B (aviation)', band: '1090 MHz / 978 MHz UAT', prefix: 'RFSAM-ADSB', status: 'new' }, { id: 'NR5G', name: '5G NR', band: 'FR1 sub-6 GHz / FR2 mmWave', prefix: 'RFSAM-NR5G', status: 'new' }, { id: 'GSM', name: 'GSM / 2G', band: '850 / 900 / 1800 / 1900 MHz', prefix: 'RFSAM-GSM', status: 'new' }, - { id: 'UWB', name: 'Ultra-Wideband', band: '3.1–10.6 GHz', prefix: 'RFSAM-UWB', status: 'new' }, + { id: 'UWB', name: 'Ultra-Wideband', band: '3.1 to 10.6 GHz', prefix: 'RFSAM-UWB', status: 'new' }, ]; diff --git a/src/data/toolchains.js b/src/data/toolchains.js index 100ed04..01833ec 100644 --- a/src/data/toolchains.js +++ b/src/data/toolchains.js @@ -1,9 +1,9 @@ // Per-technology toolchain: for each protocol, the descent (layer by layer). -// Uniform model — each layer is a list of capabilities, each with a PRIMARY tool +// Uniform model, each layer is a list of capabilities, each with a PRIMARY tool // (the thing you choose) plus what it depends on: // { tool, deps?:[slugs], role?, why?, caveat?, needs? } // The primary `tool` is the graph bubble (coloured by its own type: hardware / -// software / project). `deps` are the tools it pairs with — for a software tool +// software / project). `deps` are the tools it pairs with, for a software tool // that's the hardware it runs on; for a hardware tool that's the software it runs. // `needs` is a free-text dependency (e.g. "a host BLE adapter", "a pairing PCAP"). // All `tool`/`deps` values are slugs in the tools collection. @@ -32,11 +32,11 @@ export const toolchains = { BLE: { status: 'complete', facts: [ - { k: 'Band', v: '2.402–2.480 GHz (2.4 GHz ISM)' }, - { k: 'Channels', v: '40 × 2 MHz — 3 advertising (37/38/39) + 37 data; a connection hops every event' }, + { k: 'Band', v: '2.402 to 2.480 GHz (2.4 GHz ISM)' }, + { k: 'Channels', v: '40 × 2 MHz, 3 advertising (37/38/39) + 37 data; a connection hops every event' }, { k: 'Modulation', v: 'GFSK · PHYs: LE 1M (1 Mbps), LE 2M (BLE 5), LE Coded (long range, BLE 5)' }, { k: 'Range', v: '~10 m typical indoors; up to ~100 m+ with BLE 5 Coded PHY or higher TX power' }, - { k: 'Versions', v: '4.0 (2010) · 4.2 LE Secure Connections (2014) · 5.0 2M/Coded (2016) · 5.1–5.4' }, + { k: 'Versions', v: '4.0 (2010) · 4.2 LE Secure Connections (2014) · 5.0 2M/Coded (2016) · 5.1 to 5.4' }, ], reference: { name: 'BSAM (Tarlogic)', @@ -45,9 +45,9 @@ export const toolchains = { }, layers: { IG: { - note: 'Identify the device and its stack before any RF work — no capture yet. RFSAM defers the formal SoC/host-stack vulnerability check to the BSAM Information-Gathering controls.', + note: 'Identify the device and its stack before any RF work, no capture yet. RFSAM defers the formal SoC/host-stack vulnerability check to the BSAM Information-Gathering controls.', lookFor: [ - 'Chipset / SoC and host stack (FCC ID, teardown, advertising fingerprint) — cross-reference known Bluetooth CVEs (KNOB, SweynTooth, BLESA…).', + 'Chipset / SoC and host stack (FCC ID, teardown, advertising fingerprint), cross-reference known Bluetooth CVEs (KNOB, SweynTooth, BLESA…).', 'BLE version it speaks (4.x vs 5.x): sets which PHYs (1M / 2M / Coded) and security features are in play.', 'Advertising data: device name, advertised service UUIDs, manufacturer-specific data.', 'Address type: public vs random, and whether it rotates a Resolvable Private Address (RPA) or exposes a fixed, trackable one.', @@ -56,12 +56,12 @@ export const toolchains = { ], }, SP: { - note: 'How much of the band can you see at once? BLE spreads 40 channels over 80 MHz (2.402–2.480 GHz) and hops fast, so the radio is a visibility trade-off: a HackRF shows ~20 MHz — a slice of the band; a bladeRF in its 122.88 MHz oversampling mode shows the full 80 MHz in one pass; or camp a single channel and pick up the packets that land on it as the hopping connection passes through — cheaper and simpler, but you miss whatever is on the other channels. RTL-SDR is out: it stops near 1.766 GHz, below the 2.4 GHz band.', + note: 'How much of the band can you see at once? BLE spreads 40 channels over 80 MHz (2.402 to 2.480 GHz) and hops fast, so the radio is a visibility trade-off: a HackRF shows ~20 MHz, a slice of the band; a bladeRF in its 122.88 MHz oversampling mode shows the full 80 MHz in one pass; or camp a single channel and pick up the packets that land on it as the hopping connection passes through, cheaper and simpler, but you miss whatever is on the other channels. RTL-SDR is out: it stops near 1.766 GHz, below the 2.4 GHz band.', tools: [ - { tool: 'gqrx', role: 'Spectrum / waterfall view', why: 'See the live spectrum and pick channels — ~20 MHz at a time on a HackRF, the full 80 MHz on a bladeRF (oversampling).', deps: ['hackrf-one', 'bladerf-2-micro'] }, - { tool: 'esp32-marauder', role: 'Standalone BLE scan / wardrive', why: 'The ESP32 Marauder handheld scans and wardrives BLE devices and detects AirTags from a battery board — a no-laptop survey of advertising-channel devices in range.', caveat: 'Sees advertising/connectable devices on the advertising channels only — not an all-channel SDR view.', deps: ['esp32-s3-devkit', 'cyd', 'm5-cardputer'] }, - { tool: 'minino', role: 'BLE ADV scanner + AirTag detection', why: 'The Electronic Cats Minino (ESP32-C6) has a native BLE suite: an advertising scanner and tracker / AirTag detection from the pocket device — the EC standalone BLE survey.', caveat: '2.4 GHz advertising-channel scan; field recon, not a PCAP-grade sniffer.', deps: [] }, - { tool: 'esp32-airtag-scanner', role: 'AirTag / Find My survey', why: 'Dedicated ESP32 firmware that scans for Apple AirTag / Find My addresses and payloads with no phone — to detect trackers in the environment.', caveat: 'Passive scan only — no spoofing; payload formats may have drifted since 2024.', deps: ['esp32-devkit', 'esp32-s3-devkit'] }, + { tool: 'gqrx', role: 'Spectrum / waterfall view', why: 'See the live spectrum and pick channels, ~20 MHz at a time on a HackRF, the full 80 MHz on a bladeRF (oversampling).', deps: ['hackrf-one', 'bladerf-2-micro'] }, + { tool: 'esp32-marauder', role: 'Standalone BLE scan / wardrive', why: 'The ESP32 Marauder handheld scans and wardrives BLE devices and detects AirTags from a battery board, a no-laptop survey of advertising-channel devices in range.', caveat: 'Sees advertising/connectable devices on the advertising channels only, not an all-channel SDR view.', deps: ['esp32-s3-devkit', 'cyd', 'm5-cardputer'] }, + { tool: 'minino', role: 'BLE ADV scanner + AirTag detection', why: 'The Electronic Cats Minino (ESP32-C6) has a native BLE suite: an advertising scanner and tracker / AirTag detection from the pocket device, the EC standalone BLE survey.', caveat: '2.4 GHz advertising-channel scan; field recon, not a PCAP-grade sniffer.', deps: [] }, + { tool: 'esp32-airtag-scanner', role: 'AirTag / Find My survey', why: 'Dedicated ESP32 firmware that scans for Apple AirTag / Find My addresses and payloads with no phone, to detect trackers in the environment.', caveat: 'Passive scan only, no spoofing; payload formats may have drifted since 2024.', deps: ['esp32-devkit', 'esp32-s3-devkit'] }, { tool: 'catnip', role: 'Find My / AirTag survey', why: 'The CatSniffer AirTag-scanner firmware, run from catnip, is a standalone detector for Apple Find My / AirTag advertisements - a CatSniffer-native tracker sweep from the board, printed to the serial console.', caveat: 'Detection survey only (passive); the separate airtag_spoofer firmware transmits and is out of scope for a survey.', deps: ['catsniffer'] }, ], }, @@ -74,17 +74,17 @@ export const toolchains = { note: 'Capture and decode BLE frames. Pick a sniffer technique; each runs on its radio and exports a PCAP you dissect in Wireshark. Dedicated sniffers are simplest; the SDR path (ice9) trades setup for wider bandwidth and the ability to grab already-established connections.', decoder: 'wireshark', tools: [ - { tool: 'sniffle', role: 'Primary sniffer', why: 'Modern BT5/4.x capture with extended advertising and connection following — the default choice today. Runs on any CC1352 board.', deps: ['catsniffer'] }, - { tool: 'ice9-bluetooth-sniffer', role: 'SDR capture', why: 'All-channel capture that can also grab already-established connections. Runs on an SDR — pick it by how much of the 80 MHz band you need at once (bandwidth shown on each radio).', caveat: 'Needs CPU/GPU for channelisation.', deps: ['hackrf-one', 'bladerf-2-micro', 'usrp-b210', 'signalsdr-pro'] }, + { tool: 'sniffle', role: 'Primary sniffer', why: 'Modern BT5/4.x capture with extended advertising and connection following, the default choice today. Runs on any CC1352 board.', deps: ['catsniffer'] }, + { tool: 'ice9-bluetooth-sniffer', role: 'SDR capture', why: 'All-channel capture that can also grab already-established connections. Runs on an SDR, pick it by how much of the 80 MHz band you need at once (bandwidth shown on each radio).', caveat: 'Needs CPU/GPU for channelisation.', deps: ['hackrf-one', 'bladerf-2-micro', 'usrp-b210', 'signalsdr-pro'] }, { tool: 'nrf-sniffer', role: 'Vendor sniffer', why: 'Easiest first capture, with a turnkey Wireshark plugin.', caveat: 'Follows a single connection; less suited to adversarial work.', deps: ['nrf52840-dongle'] }, { tool: 'ubertooth-tools', role: 'Budget sniffer', why: 'Drives an Ubertooth One to follow connections on a ~$120 radio with no SDR.', caveat: 'Pre-BT5; weaker on long-lived links than CC1352 sniffers.', deps: ['ubertooth-one'] }, - { tool: 'whad', role: 'Multi-protocol sniffer', why: 'WHAD turns an nRF52840 dongle (its Butterfly firmware), an Ubertooth, or a host HCI adapter into a BLE sniffer driven from one Python framework with PCAP/Scapy output — the same toolchain you reuse for Zigbee, 802.15.4 and ESB. One workflow across protocols.', deps: ['nrf52840-dongle', 'ubertooth-one', 'usb-bt-dongle'] }, - { tool: 'catnip', role: 'CatSniffer BLE capture (EC host)', why: 'Electronic Cats’ CatSniffer host tool runs the Sniffle firmware on the CatSniffer with native Wireshark extcap, scans for Apple Find My / AirTag devices, and on Linux presents the CatSniffer as a virtual HCI (hciX) adapter for host BLE tools — the integrated EC workflow on one board.', deps: ['catsniffer'] }, - { tool: 'ghost-esp', role: 'BLE → Wireshark advertising capture', why: 'Ghost ESP logs BLE advertising-channel frames from an ESP32 straight to a Wireshark-readable capture — the cheap pocket option when a dedicated CC1352/SDR sniffer is overkill.', caveat: 'Advertising-channel capture only; for connection-following / all-channel PCAP use the dedicated sniffers above.', deps: ['esp32-devkit', 'cyd', 'm5-cardputer'] }, + { tool: 'whad', role: 'Multi-protocol sniffer', why: 'WHAD turns an nRF52840 dongle (its Butterfly firmware), an Ubertooth, or a host HCI adapter into a BLE sniffer driven from one Python framework with PCAP/Scapy output, the same toolchain you reuse for Zigbee, 802.15.4 and ESB. One workflow across protocols.', deps: ['nrf52840-dongle', 'ubertooth-one', 'usb-bt-dongle'] }, + { tool: 'catnip', role: 'CatSniffer BLE capture (EC host)', why: 'Electronic Cats’ CatSniffer host tool runs the Sniffle firmware on the CatSniffer with native Wireshark extcap, scans for Apple Find My / AirTag devices, and on Linux presents the CatSniffer as a virtual HCI (hciX) adapter for host BLE tools, the integrated EC workflow on one board.', deps: ['catsniffer'] }, + { tool: 'ghost-esp', role: 'BLE → Wireshark advertising capture', why: 'Ghost ESP logs BLE advertising-channel frames from an ESP32 straight to a Wireshark-readable capture, the cheap pocket option when a dedicated CC1352/SDR sniffer is overkill.', caveat: 'Advertising-channel capture only; for connection-following / all-channel PCAP use the dedicated sniffers above.', deps: ['esp32-devkit', 'cyd', 'm5-cardputer'] }, ], }, CR: { - note: 'Assess pairing and decrypt where the pairing was weak. No live radio of its own — it consumes a capture from the Capture step.', + note: 'Assess pairing and decrypt where the pairing was weak. No live radio of its own, it consumes a capture from the Capture step.', tools: [ { tool: 'crackle', role: 'Pairing crack / decrypt', why: 'Brute-forces the LE Legacy TK from a captured pairing event and decrypts the session.', caveat: 'No effect on LE Secure Connections (ECDH).', deps: ['wireshark'], needs: 'A PCAP of the pairing exchange: capture it at the Capture step (Sniffle / ice9 / nRF Sniffer / Ubertooth), save it from Wireshark, then feed that file to crackle.' }, ], @@ -96,19 +96,19 @@ export const toolchains = { { tool: 'btlejack', role: 'Jam & hijack', why: 'Follow, jam and hijack a live connection. Runs on ~$15 hardware.', deps: ['bbc-microbit'] }, { tool: 'injectable-firmware', role: 'Inject / MITM', why: 'Inject link-layer frames into an established connection (the InjectaBLE strategy).', deps: ['nrf52840-dongle'] }, { tool: 'bettercap', role: 'Recon & enumeration', why: 'Discover devices and enumerate GATT before/after takeover.', deps: ['usb-bt-dongle', 'catsniffer'], needs: 'A host Bluetooth LE adapter over HCI (Linux/BlueZ for the BLE module).' }, - { tool: 'esp32-marauder', role: 'BLE advertising spam / AirTag spoof', why: 'The Marauder BLE suite floods advertising spam (Apple/Sour Apple, Samsung, Swift Pair pairing popups) and spoofs AirTags from the handheld — the umbrella ESP32 BLE attack firmware.', caveat: 'Active transmit (pairing-popup spam / tracker spoofing) — authorised testing only; disruptive to all nearby devices.', deps: ['esp32-s3-devkit', 'cyd', 'm5-cardputer'] }, - { tool: 'bruce', role: 'Pairing-popup spam + Bad BLE (HID)', why: 'Bruce spams pairing popups across Apple/Android/Samsung/Windows and runs Bad BLE — HID keystroke injection over a link the target bonds to it.', caveat: 'Active transmit / HID injection — authorised testing only; Bad BLE needs the target to pair with the ESP32.', deps: ['m5-cardputer', 'cyd', 'lilygo-t-embed-cc1101', 'esp32-devkit'] }, - { tool: 'minino', role: 'BLE notification spam', why: 'The Minino (ESP32-C6) has a native BLE SPAM mode that emulates BLE devices to flood a nearby central with notification and pairing prompts — the EC pocket BLE-spam tool.', caveat: 'Active transmit — authorised testing only; disruptive to nearby devices.', deps: [] }, - { tool: 'esp32-sour-apple', role: 'iOS pairing-spam crash/DoS', why: 'A focused PoC that floods BLE pairing-request adverts to freeze or crash nearby iOS devices — more aggressive than generic popup spam.', caveat: 'Genuinely disruptive (freezes/crashes iPhones) — authorised testing only, on hardware you own. ESP32-S3 / ESP-WROOM-32; not ESP8266.', deps: ['esp32-devkit', 'esp32-s3-devkit'] }, + { tool: 'esp32-marauder', role: 'BLE advertising spam / AirTag spoof', why: 'The Marauder BLE suite floods advertising spam (Apple/Sour Apple, Samsung, Swift Pair pairing popups) and spoofs AirTags from the handheld, the umbrella ESP32 BLE attack firmware.', caveat: 'Active transmit (pairing-popup spam / tracker spoofing), authorised testing only; disruptive to all nearby devices.', deps: ['esp32-s3-devkit', 'cyd', 'm5-cardputer'] }, + { tool: 'bruce', role: 'Pairing-popup spam + Bad BLE (HID)', why: 'Bruce spams pairing popups across Apple/Android/Samsung/Windows and runs Bad BLE, HID keystroke injection over a link the target bonds to it.', caveat: 'Active transmit / HID injection, authorised testing only; Bad BLE needs the target to pair with the ESP32.', deps: ['m5-cardputer', 'cyd', 'lilygo-t-embed-cc1101', 'esp32-devkit'] }, + { tool: 'minino', role: 'BLE notification spam', why: 'The Minino (ESP32-C6) has a native BLE SPAM mode that emulates BLE devices to flood a nearby central with notification and pairing prompts, the EC pocket BLE-spam tool.', caveat: 'Active transmit, authorised testing only; disruptive to nearby devices.', deps: [] }, + { tool: 'esp32-sour-apple', role: 'iOS pairing-spam crash/DoS', why: 'A focused PoC that floods BLE pairing-request adverts to freeze or crash nearby iOS devices, more aggressive than generic popup spam.', caveat: 'Genuinely disruptive (freezes/crashes iPhones), authorised testing only, on hardware you own. ESP32-S3 / ESP-WROOM-32; not ESP8266.', deps: ['esp32-devkit', 'esp32-s3-devkit'] }, ], }, AP: { note: 'Interact with what the device trusts above the link, over the host’s own HCI controller.', tools: [ - { tool: 'bleak', role: 'GATT interaction', why: 'Script reads/writes/subscriptions and replay learned commands, cross-platform.', deps: ['usb-bt-dongle', 'catsniffer'], needs: 'A host BLE controller over HCI — a standard USB Bluetooth adapter, or a CatSniffer presented as a virtual HCI on Linux via the catnip tool.' }, + { tool: 'bleak', role: 'GATT interaction', why: 'Script reads/writes/subscriptions and replay learned commands, cross-platform.', deps: ['usb-bt-dongle', 'catsniffer'], needs: 'A host BLE controller over HCI, a standard USB Bluetooth adapter, or a CatSniffer presented as a virtual HCI on Linux via the catnip tool.' }, { tool: 'bettercap', role: 'GATT enumeration', why: 'Enumerate services and characteristics interactively.', deps: ['usb-bt-dongle', 'catsniffer'], needs: 'A host Bluetooth LE adapter over HCI (Linux/BlueZ for the BLE module).' }, - { tool: 'bruce', role: 'GATT / HID interaction (Bad BLE)', why: 'Beyond spam, Bruce acts above the link — Bad BLE drives HID and media commands to a host that has bonded with the ESP32, exercising what the device trusts.', caveat: 'Requires the target to pair/bond with the ESP32 first; authorised testing only.', deps: ['m5-cardputer', 'cyd', 'esp32-devkit'] }, - { tool: 'minino', role: 'BLE HID', why: 'The Minino native BLE HID component presents the EC board as a Bluetooth input device to a host — the EC path for testing what a host trusts from a paired peripheral.', caveat: 'Authorised testing only; the host must pair with the device.', deps: [] }, + { tool: 'bruce', role: 'GATT / HID interaction (Bad BLE)', why: 'Beyond spam, Bruce acts above the link, Bad BLE drives HID and media commands to a host that has bonded with the ESP32, exercising what the device trusts.', caveat: 'Requires the target to pair/bond with the ESP32 first; authorised testing only.', deps: ['m5-cardputer', 'cyd', 'esp32-devkit'] }, + { tool: 'minino', role: 'BLE HID', why: 'The Minino native BLE HID component presents the EC board as a Bluetooth input device to a host, the EC path for testing what a host trusts from a paired peripheral.', caveat: 'Authorised testing only; the host must pair with the device.', deps: [] }, ], }, }, @@ -117,81 +117,81 @@ export const toolchains = { WIFI: { status: 'complete', facts: [ - { k: 'Band', v: '2.4 GHz (2.400–2.4835 GHz) · 5 GHz (UNII bands, ~5.15–5.85 GHz) · 6 GHz (5.925–7.125 GHz, Wi-Fi 6E/7)' }, - { k: 'Channels', v: '2.4 GHz: 1–14 (1–11 in the US; only 1/6/11 non-overlapping) · 5 GHz: ~25, many gated by DFS · 6 GHz: up to 59 × 20 MHz · widths 20/40/80/160 (320 in Wi-Fi 7)' }, + { k: 'Band', v: '2.4 GHz (2.400 to 2.4835 GHz) · 5 GHz (UNII bands, ~5.15 to 5.85 GHz) · 6 GHz (5.925 to 7.125 GHz, Wi-Fi 6E/7)' }, + { k: 'Channels', v: '2.4 GHz: 1 to 14 (1 to 11 in the US; only 1/6/11 non-overlapping) · 5 GHz: ~25, many gated by DFS · 6 GHz: up to 59 × 20 MHz · widths 20/40/80/160 (320 in Wi-Fi 7)' }, { k: 'Standards', v: '802.11 b/g/n (2.4) · a/n/ac (5) · ax = Wi-Fi 6 (2.4/5) & 6E (adds 6 GHz) · be = Wi-Fi 7' }, { k: 'Security', v: 'Open · WEP (broken) · WPA/WPA2-PSK (handshake, PMKID) · WPA2/WPA3-Enterprise (802.1X/EAP) · WPA3-SAE · OWE. WPS PIN is a common weak point; WPA3 mandatory on 6 GHz.' }, - { k: 'Range', v: '~10–50 m indoors; 100 m+ outdoors at 2.4 GHz; 5/6 GHz trade range for throughput. High-gain / amplified adapters extend reach.' }, + { k: 'Range', v: '~10 to 50 m indoors; 100 m+ outdoors at 2.4 GHz; 5/6 GHz trade range for throughput. High-gain / amplified adapters extend reach.' }, ], reference: null, layers: { IG: { - note: 'Fingerprint the access point or client before any RF work — no capture yet. The goal is to know what you are dealing with: which radio chipset and firmware it runs, which Wi-Fi generation and bands it speaks, how it secures itself, and whether legacy weak points (WEP, WPS) are switched on. Most of this is readable passively from the beacons the AP already shouts, plus the FCC ID on the label.', + note: 'Fingerprint the access point or client before any RF work, no capture yet. The goal is to know what you are dealing with: which radio chipset and firmware it runs, which Wi-Fi generation and bands it speaks, how it secures itself, and whether legacy weak points (WEP, WPS) are switched on. Most of this is readable passively from the beacons the AP already shouts, plus the FCC ID on the label.', lookFor: [ - 'Chipset / SoC and firmware (FCC ID, teardown, OUI of the BSSID) — cross-reference known Wi-Fi CVEs (KRACK on WPA2, FragAttacks, Dragonblood on WPA3-SAE, vendor WPS/firmware bugs).', + 'Chipset / SoC and firmware (FCC ID, teardown, OUI of the BSSID), cross-reference known Wi-Fi CVEs (KRACK on WPA2, FragAttacks, Dragonblood on WPA3-SAE, vendor WPS/firmware bugs).', 'Standard and bands it speaks (802.11 b/g/n/ac/ax/be; 2.4 vs 5 vs 6 GHz): sets which channels to survey and which radios you need.', - 'SSID and BSSID: the network name and the AP’s MAC — plus whether the SSID is hidden and whether several BSSIDs share one physical AP.', + 'SSID and BSSID: the network name and the AP’s MAC, plus whether the SSID is hidden and whether several BSSIDs share one physical AP.', 'Security mode from the beacon’s RSN/WPA information element: Open / WEP / WPA2-PSK / WPA3-SAE / OWE / WPA-Enterprise (802.1X), and the cipher (TKIP vs CCMP/GCMP).', 'WPS state: is WPS (especially the 8-digit PIN method) enabled? It is the single most common shortcut into an otherwise strong WPA2 network.', 'Clients already associated: their MACs, signal strength and probe requests (which reveal networks those devices have joined before).', ], }, SP: { - note: 'How much of the air can you see at once, and where is the target? Wi-Fi spans three bands and dozens of channels, and a radio only listens to one channel at a time — so a survey means hopping channels and logging every AP and client it hears. A standard monitor-mode adapter covers 2.4 and 5 GHz; 6 GHz (Wi-Fi 6E/7) needs a 6 GHz-capable radio. This step is the map: enumerate the networks, their channels, security and clients before you commit to a target.', + note: 'How much of the air can you see at once, and where is the target? Wi-Fi spans three bands and dozens of channels, and a radio only listens to one channel at a time, so a survey means hopping channels and logging every AP and client it hears. A standard monitor-mode adapter covers 2.4 and 5 GHz; 6 GHz (Wi-Fi 6E/7) needs a 6 GHz-capable radio. This step is the map: enumerate the networks, their channels, security and clients before you commit to a target.', tools: [ - { tool: 'kismet', role: 'Survey & wardriving', why: 'The reference passive survey tool: channel-hops across 2.4/5 (and 6 GHz with capable hardware), logs every AP/client/SSID with GPS, and never transmits — ideal for a quiet map of the environment.', caveat: 'Passive only; 6 GHz needs a Wi-Fi 6E-capable adapter.', deps: ['alfa-awus036ach'] }, - { tool: 'aircrack-ng', role: 'Channel survey', why: 'airodump-ng gives a live table of APs and associated clients — BSSID, channel, encryption, signal — the fastest way to lock onto a target and read its security mode.', deps: ['alfa-awus036ach'] }, + { tool: 'kismet', role: 'Survey & wardriving', why: 'The reference passive survey tool: channel-hops across 2.4/5 (and 6 GHz with capable hardware), logs every AP/client/SSID with GPS, and never transmits, ideal for a quiet map of the environment.', caveat: 'Passive only; 6 GHz needs a Wi-Fi 6E-capable adapter.', deps: ['alfa-awus036ach'] }, + { tool: 'aircrack-ng', role: 'Channel survey', why: 'airodump-ng gives a live table of APs and associated clients, BSSID, channel, encryption, signal, the fastest way to lock onto a target and read its security mode.', deps: ['alfa-awus036ach'] }, { tool: 'minino', role: 'Pocket scanner / wardriving', why: 'Electronic Cats ESP32-C6 multitool: standalone SSID/AP scanning and wardriving with onboard GPS/microSD and an analyzer view, no laptop needed.', caveat: '2.4 GHz only (ESP32-C6 has no 5/6 GHz radio).', deps: [] }, - { tool: 'esp32-marauder', role: 'Pocket survey / GPS wardrive', why: 'The ESP32 Marauder handheld scans APs and stations and wardrives with GPS, logging to SD — a no-laptop 2.4 GHz survey on a $5–15 board (CYD, Cardputer, bare ESP32).', caveat: '2.4 GHz only (ESP32 has no 5/6 GHz radio); a quick survey, not full Kismet coverage.', deps: ['esp32-devkit', 'cyd', 'm5-cardputer', 'flipper-wifi-devboard'] }, - { tool: 'ghost-esp', role: 'AP / station scan', why: 'Ghost ESP scans nearby APs and associated clients from the ESP32 console — an alternative pocket survey firmware (Bruce does the same).', caveat: '2.4 GHz only.', deps: ['esp32-devkit', 'cyd', 'm5-cardputer'] }, + { tool: 'esp32-marauder', role: 'Pocket survey / GPS wardrive', why: 'The ESP32 Marauder handheld scans APs and stations and wardrives with GPS, logging to SD, a no-laptop 2.4 GHz survey on a $5 to 15 board (CYD, Cardputer, bare ESP32).', caveat: '2.4 GHz only (ESP32 has no 5/6 GHz radio); a quick survey, not full Kismet coverage.', deps: ['esp32-devkit', 'cyd', 'm5-cardputer', 'flipper-wifi-devboard'] }, + { tool: 'ghost-esp', role: 'AP / station scan', why: 'Ghost ESP scans nearby APs and associated clients from the ESP32 console, an alternative pocket survey firmware (Bruce does the same).', caveat: '2.4 GHz only.', deps: ['esp32-devkit', 'cyd', 'm5-cardputer'] }, ], }, PHY: { - note: 'No standalone Wi-Fi demodulator in this kit. The capture tools demodulate the OFDM/DSSS waveform (PHY) and frame the 802.11 packets (LL) together on the adapter’s own chipset, so they live at the Capture step. A wide-band SDR can stare at the spectrum, but decoding live 802.11ac/ax in software is impractical — use a real monitor-mode adapter.', + note: 'No standalone Wi-Fi demodulator in this kit. The capture tools demodulate the OFDM/DSSS waveform (PHY) and frame the 802.11 packets (LL) together on the adapter’s own chipset, so they live at the Capture step. A wide-band SDR can stare at the spectrum, but decoding live 802.11ac/ax in software is impractical, use a real monitor-mode adapter.', }, LL: { - note: 'Capture and decode raw 802.11 frames. Put the adapter into monitor mode, park it on the target’s channel, and it pulls beacons, probes, management/control frames and the EAPOL handshake off the air into a PCAP you open in Wireshark. Pick a capture tool — a quick targeted grab (airodump-ng), a logged survey capture (Kismet), or a handshake/PMKID grab (hcxdumptool).', + note: 'Capture and decode raw 802.11 frames. Put the adapter into monitor mode, park it on the target’s channel, and it pulls beacons, probes, management/control frames and the EAPOL handshake off the air into a PCAP you open in Wireshark. Pick a capture tool, a quick targeted grab (airodump-ng), a logged survey capture (Kismet), or a handshake/PMKID grab (hcxdumptool).', decoder: 'wireshark', tools: [ { tool: 'aircrack-ng', role: 'Primary capture', why: 'airodump-ng is the default monitor-mode capture: lock a channel/BSSID and write a PCAP, optionally firing a deauth to force a client to re-handshake. Simplest path to a 4-way handshake.', deps: ['alfa-awus036ach'] }, - { tool: 'hcxdumptool', role: 'Handshake / PMKID capture', why: 'Purpose-built to grab the WPA/WPA2 PMKID straight from the AP — often clientless, no waiting for a client to reconnect — and EAPOL handshakes, written as pcapng for offline cracking.', caveat: 'Aggressive by default; recent versions dropped some active-attack flags — check the docs for your version.', deps: ['alfa-awus036ach'] }, + { tool: 'hcxdumptool', role: 'Handshake / PMKID capture', why: 'Purpose-built to grab the WPA/WPA2 PMKID straight from the AP, often clientless, no waiting for a client to reconnect, and EAPOL handshakes, written as pcapng for offline cracking.', caveat: 'Aggressive by default; recent versions dropped some active-attack flags, check the docs for your version.', deps: ['alfa-awus036ach'] }, { tool: 'kismet', role: 'Logged capture', why: 'Captures while it surveys: every frame it hears is logged to pcapng with metadata, so the survey and the capture are one artefact you replay in Wireshark.', deps: ['alfa-awus036ach'] }, - { tool: 'minino', role: 'Pocket sniffer', why: 'Standalone 2.4 GHz Wi-Fi sniffer that writes captures to microSD with Wireshark-compatible output — capture without a host PC.', caveat: '2.4 GHz only; management/handshake frames, not 5/6 GHz traffic.', deps: [] }, - { tool: 'esp32-marauder', role: 'Handshake / PMKID capture', why: 'The Marauder EAPOL/PMKID scan grabs WPA/WPA2 key material straight to an SD-card PCAP from the handheld — capture in the field, crack offline in hashcat.', caveat: '2.4 GHz, WPA/WPA2 only; captures material only. SD card required (v0.11.0+).', deps: ['esp32-devkit', 'cyd', 'm5-cardputer'] }, - { tool: 'esp32-wifi-penetration-tool', role: 'PMKID → HCCAPX (web-driven)', why: 'A bare-ESP32 framework that captures PMKID/handshakes (passive, rogue-AP or forced re-auth), exports PCAP and converts to a hashcat-ready HCCAPX — all from an on-device web UI, no screen needed.', caveat: '2.4 GHz, WPA/WPA2; captures key material only — crack off-device in hashcat.', deps: ['esp32-devkit'] }, + { tool: 'minino', role: 'Pocket sniffer', why: 'Standalone 2.4 GHz Wi-Fi sniffer that writes captures to microSD with Wireshark-compatible output, capture without a host PC.', caveat: '2.4 GHz only; management/handshake frames, not 5/6 GHz traffic.', deps: [] }, + { tool: 'esp32-marauder', role: 'Handshake / PMKID capture', why: 'The Marauder EAPOL/PMKID scan grabs WPA/WPA2 key material straight to an SD-card PCAP from the handheld, capture in the field, crack offline in hashcat.', caveat: '2.4 GHz, WPA/WPA2 only; captures material only. SD card required (v0.11.0+).', deps: ['esp32-devkit', 'cyd', 'm5-cardputer'] }, + { tool: 'esp32-wifi-penetration-tool', role: 'PMKID → HCCAPX (web-driven)', why: 'A bare-ESP32 framework that captures PMKID/handshakes (passive, rogue-AP or forced re-auth), exports PCAP and converts to a hashcat-ready HCCAPX, all from an on-device web UI, no screen needed.', caveat: '2.4 GHz, WPA/WPA2; captures key material only, crack off-device in hashcat.', deps: ['esp32-devkit'] }, ], }, CR: { - note: 'Assess the crypto and recover the key where it is weak. None of these have a radio of their own — they consume a capture from the Capture step. WPA/WPA2-PSK falls to an offline attack on the captured handshake or PMKID; WPS PIN falls to an online attack on the AP; WEP is trivially broken. WPA3-SAE and OWE resist offline cracking by design (though Dragonblood-class bugs exist on some implementations).', + note: 'Assess the crypto and recover the key where it is weak. None of these have a radio of their own, they consume a capture from the Capture step. WPA/WPA2-PSK falls to an offline attack on the captured handshake or PMKID; WPS PIN falls to an online attack on the AP; WEP is trivially broken. WPA3-SAE and OWE resist offline cracking by design (though Dragonblood-class bugs exist on some implementations).', tools: [ { tool: 'hashcat', role: 'WPA/WPA2 cracker (GPU)', why: 'The fastest offline cracker: mode 22000 handles both 4-way-handshake and PMKID hashes with GPU dictionary, rule and mask attacks.', deps: ['wireshark'], needs: 'A WPA/WPA2 handshake or PMKID captured at the Capture step (airodump-ng or hcxdumptool). Convert the pcapng to a .hc22000 hash with hcxpcapngtool (hcxtools), then feed it to hashcat.' }, - { tool: 'hcxtools', role: 'Capture → hash converter', why: 'hcxpcapngtool turns a captured pcapng into the .hc22000 hash format hashcat (and John) crack — the glue between capture and cracking.', deps: ['wireshark'], needs: 'The pcapng written by hcxdumptool or airodump-ng at the Capture step.' }, - { tool: 'aircrack-ng', role: 'Handshake / WEP cracker', why: 'Cracks WEP outright and runs a CPU dictionary attack against a captured WPA/WPA2 handshake — the all-in-one option when you don’t want a separate GPU step.', deps: ['wireshark'], needs: 'A .cap/.pcap containing the 4-way handshake from the Capture step (airodump-ng), plus a wordlist.' }, - { tool: 'reaver', role: 'WPS PIN attack', why: 'Attacks the WPS registration PIN — including the offline Pixie-Dust attack — to recover the WPA passphrase directly from a vulnerable AP, bypassing the handshake entirely.', deps: ['alfa-awus036ach'], needs: 'Runs live against the AP over an injection-capable adapter (not from a PCAP); only works where WPS is enabled and unpatched.' }, + { tool: 'hcxtools', role: 'Capture → hash converter', why: 'hcxpcapngtool turns a captured pcapng into the .hc22000 hash format hashcat (and John) crack, the glue between capture and cracking.', deps: ['wireshark'], needs: 'The pcapng written by hcxdumptool or airodump-ng at the Capture step.' }, + { tool: 'aircrack-ng', role: 'Handshake / WEP cracker', why: 'Cracks WEP outright and runs a CPU dictionary attack against a captured WPA/WPA2 handshake, the all-in-one option when you don’t want a separate GPU step.', deps: ['wireshark'], needs: 'A .cap/.pcap containing the 4-way handshake from the Capture step (airodump-ng), plus a wordlist.' }, + { tool: 'reaver', role: 'WPS PIN attack', why: 'Attacks the WPS registration PIN, including the offline Pixie-Dust attack, to recover the WPA passphrase directly from a vulnerable AP, bypassing the handshake entirely.', deps: ['alfa-awus036ach'], needs: 'Runs live against the AP over an injection-capable adapter (not from a PCAP); only works where WPS is enabled and unpatched.' }, ], }, AT: { - note: 'Actively disrupt, take over or impersonate. Pick the technique; each names the injection-capable radio it runs on. Deauthentication frames knock clients off (to force a handshake or as denial-of-service); a rogue AP / evil twin clones the target SSID so clients associate to you. Note WPA3’s Protected Management Frames (PMF / 802.11w) blunt classic deauth — check the target’s PMF setting first.', + note: 'Actively disrupt, take over or impersonate. Pick the technique; each names the injection-capable radio it runs on. Deauthentication frames knock clients off (to force a handshake or as denial-of-service); a rogue AP / evil twin clones the target SSID so clients associate to you. Note WPA3’s Protected Management Frames (PMF / 802.11w) blunt classic deauth, check the target’s PMF setting first.', tools: [ - { tool: 'aircrack-ng', role: 'Deauth / disconnect', why: 'aireplay-ng sends targeted or broadcast deauthentication frames to drop clients — to capture a fresh handshake or as a quick DoS.', caveat: 'Blocked by 802.11w/PMF (common on WPA3 and newer WPA2).', deps: ['alfa-awus036ach'] }, - { tool: 'mdk4', role: 'Stress / flood attacks', why: 'Broad 802.11 fuzzing/DoS toolkit: deauth floods, beacon floods (fake SSIDs), authentication floods and more — for resilience testing of an AP.', caveat: 'Noisy and disruptive; PMF mitigates the deauth modes.', deps: ['alfa-awus036ach'] }, + { tool: 'aircrack-ng', role: 'Deauth / disconnect', why: 'aireplay-ng sends targeted or broadcast deauthentication frames to drop clients, to capture a fresh handshake or as a quick DoS.', caveat: 'Blocked by 802.11w/PMF (common on WPA3 and newer WPA2).', deps: ['alfa-awus036ach'] }, + { tool: 'mdk4', role: 'Stress / flood attacks', why: 'Broad 802.11 fuzzing/DoS toolkit: deauth floods, beacon floods (fake SSIDs), authentication floods and more, for resilience testing of an AP.', caveat: 'Noisy and disruptive; PMF mitigates the deauth modes.', deps: ['alfa-awus036ach'] }, { tool: 'bettercap', role: 'Recon & deauth', why: 'Scriptable framework with a wifi module: enumerate APs/clients, fire deauths and capture handshakes from one console.', deps: ['alfa-awus036ach'] }, - { tool: 'minino', role: 'Pocket deauther / DoS', why: 'Standalone 2.4 GHz deauther and DoS from its console, plus a deauth-detection mode to spot the same attack against you — a field tool with no laptop.', caveat: '2.4 GHz only; deauth blocked by 802.11w/PMF targets.', deps: [] }, - { tool: 'wifi-pineapple', role: 'Rogue AP / evil twin', why: 'Turnkey platform that automates evil-twin, client-capture and recon — clone an SSID and harvest associations without scripting.', deps: [] }, - { tool: 'esp32-marauder', role: 'Deauth / beacon & probe spam', why: 'Fires targeted or broadcast deauth, beacon spam (fake-SSID floods) and probe floods from the handheld — to force a re-handshake or stress an AP, no laptop needed.', caveat: 'Authorised testing only. 2.4 GHz; deauth blocked by 802.11w/PMF (WPA3 and newer WPA2).', deps: ['esp32-devkit', 'cyd', 'm5-cardputer', 'flipper-wifi-devboard'] }, - { tool: 'bruce', role: 'Deauth from handheld', why: 'The Bruce Wi-Fi menu sends deauthentication frames, plus wardriving and EAPOL capture, on M5Stack/LilyGo/CYD hardware — the broad red-team multitool alternative.', caveat: 'Authorised testing only. 2.4 GHz; blocked by PMF.', deps: ['m5-cardputer', 'cyd', 'lilygo-t-embed-cc1101', 'esp32-devkit'] }, - { tool: 'esp32-deauther-ganesh', role: 'Bare-ESP32 deauth', why: 'The minimal ESP32 deauther — the canonical esp_wifi_80211_tx injection path on a plain board with no display, when all you need is the deauth primitive.', caveat: 'Authorised testing only; blocked by PMF. Unmaintained since 2021, no license — confirm it builds on current ESP-IDF.', deps: ['esp32-devkit'] }, + { tool: 'minino', role: 'Pocket deauther / DoS', why: 'Standalone 2.4 GHz deauther and DoS from its console, plus a deauth-detection mode to spot the same attack against you, a field tool with no laptop.', caveat: '2.4 GHz only; deauth blocked by 802.11w/PMF targets.', deps: [] }, + { tool: 'wifi-pineapple', role: 'Rogue AP / evil twin', why: 'Turnkey platform that automates evil-twin, client-capture and recon, clone an SSID and harvest associations without scripting.', deps: [] }, + { tool: 'esp32-marauder', role: 'Deauth / beacon & probe spam', why: 'Fires targeted or broadcast deauth, beacon spam (fake-SSID floods) and probe floods from the handheld, to force a re-handshake or stress an AP, no laptop needed.', caveat: 'Authorised testing only. 2.4 GHz; deauth blocked by 802.11w/PMF (WPA3 and newer WPA2).', deps: ['esp32-devkit', 'cyd', 'm5-cardputer', 'flipper-wifi-devboard'] }, + { tool: 'bruce', role: 'Deauth from handheld', why: 'The Bruce Wi-Fi menu sends deauthentication frames, plus wardriving and EAPOL capture, on M5Stack/LilyGo/CYD hardware, the broad red-team multitool alternative.', caveat: 'Authorised testing only. 2.4 GHz; blocked by PMF.', deps: ['m5-cardputer', 'cyd', 'lilygo-t-embed-cc1101', 'esp32-devkit'] }, + { tool: 'esp32-deauther-ganesh', role: 'Bare-ESP32 deauth', why: 'The minimal ESP32 deauther, the canonical esp_wifi_80211_tx injection path on a plain board with no display, when all you need is the deauth primitive.', caveat: 'Authorised testing only; blocked by PMF. Unmaintained since 2021, no license, confirm it builds on current ESP-IDF.', deps: ['esp32-devkit'] }, ], }, AP: { - note: 'Once a client is on your network (or coerced onto a clone of theirs), test what it trusts above the link: the captive portal, the credentials it submits, and the traffic you can now man-in-the-middle. This is where an evil-twin pays off — present a convincing portal, or sit between the client and the upstream and inspect/alter its flows.', + note: 'Once a client is on your network (or coerced onto a clone of theirs), test what it trusts above the link: the captive portal, the credentials it submits, and the traffic you can now man-in-the-middle. This is where an evil-twin pays off, present a convincing portal, or sit between the client and the upstream and inspect/alter its flows.', tools: [ { tool: 'wifiphisher', role: 'Rogue-AP / captive portal', why: 'Automates the evil-twin plus a phishing captive portal (fake firmware-upgrade, router-login, OAuth pages) to harvest the Wi-Fi passphrase or web credentials post-association.', caveat: 'Social-engineering attack; needs a believable pretext and a deauth to move the client over.', deps: ['alfa-awus036ach'] }, { tool: 'eaphammer', role: 'Enterprise evil twin', why: 'Targets WPA2/WPA3-Enterprise (802.1X): stands up a hostile RADIUS/AP to capture EAP (MSCHAPv2) credentials and run hostile-portal pivots.', deps: ['alfa-awus036ach'], needs: 'A target running WPA-Enterprise (802.1X/EAP), not PSK.' }, { tool: 'hostapd-mana', role: 'Credential-harvesting AP', why: 'SensePost’s patched hostapd (the engine under eaphammer): a “MANA” rogue AP that lures clients via their probe history and captures EAP/Enterprise credentials.', deps: ['alfa-awus036ach'] }, { tool: 'bettercap', role: 'Post-association MITM', why: 'Once the client is on the network, run ARP/DNS spoofing, an HTTP(S) proxy and traffic capture to inspect and tamper with its app-layer flows.', deps: ['alfa-awus036ach'] }, - { tool: 'esp32-marauder', role: 'Evil Portal credential harvest', why: 'Spawns a rogue AP with a captive-portal login page and logs submitted credentials to SD/serial — the above-the-link phishing test from a handheld (Bruce and Ghost ESP do the same).', caveat: 'Authorised / social-engineering engagement only; harvesting third-party credentials without consent is illegal. Needs an SD card and a believable pretext.', deps: ['esp32-devkit', 'cyd', 'm5-cardputer'] }, - { tool: 'esp32-projectzero', role: 'Verifying captive portal + WPA3-SAE overflow', why: 'A two-board evil-twin whose captive portal verifies the entered Wi-Fi password against the real AP, plus a WPA3-SAE overflow mode — a more specialised rogue-portal variant.', caveat: 'Authorised testing only; low-maturity project — verify behaviour first. Needs two ESP32/C5 boards.', deps: ['esp32-devkit'] }, + { tool: 'esp32-marauder', role: 'Evil Portal credential harvest', why: 'Spawns a rogue AP with a captive-portal login page and logs submitted credentials to SD/serial, the above-the-link phishing test from a handheld (Bruce and Ghost ESP do the same).', caveat: 'Authorised / social-engineering engagement only; harvesting third-party credentials without consent is illegal. Needs an SD card and a believable pretext.', deps: ['esp32-devkit', 'cyd', 'm5-cardputer'] }, + { tool: 'esp32-projectzero', role: 'Verifying captive portal + WPA3-SAE overflow', why: 'A two-board evil-twin whose captive portal verifies the entered Wi-Fi password against the real AP, plus a WPA3-SAE overflow mode, a more specialised rogue-portal variant.', caveat: 'Authorised testing only; low-maturity project, verify behaviour first. Needs two ESP32/C5 boards.', deps: ['esp32-devkit'] }, ], }, }, diff --git a/src/data/toolchains/adsb.js b/src/data/toolchains/adsb.js index 62bd161..5b1d144 100644 --- a/src/data/toolchains/adsb.js +++ b/src/data/toolchains/adsb.js @@ -5,53 +5,53 @@ export default { { "k": "Signal (1090ES)", "v": "Pulse-Position Modulation (PPM) at 1 Mbps on a 1090 MHz carrier; an Extended Squitter is a 112-bit message (8 µs preamble + 112 µs data). 978 UAT uses a different ~1.04 Mbps waveform with a longer 272-bit message." }, { "k": "Messages", "v": "ADS-B 'out' rides Mode S downlink format DF17 (transponder-equipped aircraft) and DF18 (non-transponder / TIS-B). Each carries the 24-bit ICAO aircraft address plus a type code: identification (callsign), airborne/surface position (CPR-encoded), and velocity." }, { "k": "Identifiers", "v": "ICAO 24-bit address (the aircraft's unique radio ID), the 8-character flight callsign, and the CPR-encoded latitude/longitude. None of these are authenticated, so any of them can be forged." }, - { "k": "Security", "v": "ADS-B is BROADCAST and UNENCRYPTED — there is nothing to decrypt. The signal structure is public and any receiver decodes it. There is also NO authentication or integrity on the link: a receiver cannot tell a genuine aircraft from a forged frame, which is exactly what makes spoofing/injection possible." } + { "k": "Security", "v": "ADS-B is BROADCAST and UNENCRYPTED, there is nothing to decrypt. The signal structure is public and any receiver decodes it. There is also NO authentication or integrity on the link: a receiver cannot tell a genuine aircraft from a forged frame, which is exactly what makes spoofing/injection possible." } ], "reference": null, "layers": { "IG": { - "note": "Work out what you are listening for before touching the air — there is no capture yet. ADS-B has two flavours: 1090 MHz Extended Squitter (1090ES), used worldwide, and 978 MHz UAT, used in the US for lower-altitude general aviation. The defining fact for security work: ADS-B is a one-way, unencrypted, unauthenticated broadcast — the entire game is to receive and decode it, and the only 'attack' the link permits is imitating a signal it cannot verify. Identify which link the target uses, which message types it emits, and which identifiers it exposes.", + "note": "Work out what you are listening for before touching the air, there is no capture yet. ADS-B has two flavours: 1090 MHz Extended Squitter (1090ES), used worldwide, and 978 MHz UAT, used in the US for lower-altitude general aviation. The defining fact for security work: ADS-B is a one-way, unencrypted, unauthenticated broadcast, the entire game is to receive and decode it, and the only 'attack' the link permits is imitating a signal it cannot verify. Identify which link the target uses, which message types it emits, and which identifiers it exposes.", "lookFor": [ "Which link to receive: 1090 MHz Mode S Extended Squitter (1090ES, everywhere) vs 978 MHz UAT (US general aviation). This sets the frequency you tune and the decoder you run (dump1090/readsb for 1090, dump978 for UAT).", - "That the link is unauthenticated and unencrypted: positions, callsigns and the ICAO address are broadcast in the clear with no integrity check — there is no key to recover and no crypto to break, only a signal to imitate.", - "The 24-bit ICAO aircraft address — the unique radio identity in every frame, and how you tell aircraft apart and key any tracking or plausibility check.", - "The message / downlink-format mix: DF17 (transponder ADS-B) vs DF18 (TIS-B / non-transponder), and which type codes are present — aircraft identification (callsign), airborne/surface position (CPR-encoded), velocity.", - "The receiver/antenna side of your own setup: 1090 MHz wants a quarter-wave (~6.9 cm) antenna and, for weak/distant traffic, a 1090 MHz band-pass filter and an LNA — the difference between a handful of local aircraft and hundreds.", - "What downstream system trusts the feed (a tracking display, TCAS-style collision logic, an aggregator) — that is what a spoof or a flood of forged aircraft actually disrupts." + "That the link is unauthenticated and unencrypted: positions, callsigns and the ICAO address are broadcast in the clear with no integrity check, there is no key to recover and no crypto to break, only a signal to imitate.", + "The 24-bit ICAO aircraft address, the unique radio identity in every frame, and how you tell aircraft apart and key any tracking or plausibility check.", + "The message / downlink-format mix: DF17 (transponder ADS-B) vs DF18 (TIS-B / non-transponder), and which type codes are present, aircraft identification (callsign), airborne/surface position (CPR-encoded), velocity.", + "The receiver/antenna side of your own setup: 1090 MHz wants a quarter-wave (~6.9 cm) antenna and, for weak/distant traffic, a 1090 MHz band-pass filter and an LNA, the difference between a handful of local aircraft and hundreds.", + "What downstream system trusts the feed (a tracking display, TCAS-style collision logic, an aggregator), that is what a spoof or a flood of forged aircraft actually disrupts." ] }, "SP": { - "note": "Confirm 1090 MHz energy is actually present and judge the RF environment before decoding. ADS-B sits at 1090 MHz (and 978 MHz for UAT), well within reach of almost any SDR. On a waterfall you will see short, bursty pulses popping up at 1090 MHz as aircraft squitter — unlike GNSS, ADS-B is above the noise floor and visibly bursty, so you can confirm the band is alive and gauge how busy the sky is before committing a decoder. This step also sizes up your antenna/filter chain: a 1090 MHz band-pass filter and LNA dramatically lift weak traffic. The RTL-SDR is the canonical, cheap 1090 receiver and reaches both 1090 and 978 MHz.", + "note": "Confirm 1090 MHz energy is actually present and judge the RF environment before decoding. ADS-B sits at 1090 MHz (and 978 MHz for UAT), well within reach of almost any SDR. On a waterfall you will see short, bursty pulses popping up at 1090 MHz as aircraft squitter, unlike GNSS, ADS-B is above the noise floor and visibly bursty, so you can confirm the band is alive and gauge how busy the sky is before committing a decoder. This step also sizes up your antenna/filter chain: a 1090 MHz band-pass filter and LNA dramatically lift weak traffic. The RTL-SDR is the canonical, cheap 1090 receiver and reaches both 1090 and 978 MHz.", "tools": [ - { "tool": "gqrx", "role": "Spectrum / waterfall view", "why": "Tune to 1090 MHz (or 978 for UAT) and watch the waterfall for the short bursty Extended-Squitter pulses — confirm the band is active, see how busy the sky is, and check your antenna/filter chain is feeding signal before you start a decoder.", "caveat": "Only confirms that pulses are present; it does not decode frames — that is the Capture step. A 1090 MHz band-pass filter + LNA greatly improves weak/distant traffic.", "deps": ["rtl-sdr-v4", "hackrf-one", "bladerf-2-micro", "usrp-b210"] } + { "tool": "gqrx", "role": "Spectrum / waterfall view", "why": "Tune to 1090 MHz (or 978 for UAT) and watch the waterfall for the short bursty Extended-Squitter pulses, confirm the band is active, see how busy the sky is, and check your antenna/filter chain is feeding signal before you start a decoder.", "caveat": "Only confirms that pulses are present; it does not decode frames, that is the Capture step. A 1090 MHz band-pass filter + LNA greatly improves weak/distant traffic.", "deps": ["rtl-sdr-v4", "hackrf-one", "bladerf-2-micro", "usrp-b210"] } ] }, "PHY": { - "note": "No standalone ADS-B demodulator in this kit, and none needed as a separate stage: every ADS-B tool demodulates the 1 Mbps PPM waveform (PHY) and frames/decodes the 112-bit Extended Squitter (LL) together in one pass, so they live at the Capture step. The PHY job here is just a clean capture — a quarter-wave 1090 MHz antenna, ideally a band-pass filter and LNA, into an RTL-SDR. There is no I/Q stage to drive by hand: the decoder correlates the preamble and recovers the bits itself." + "note": "No standalone ADS-B demodulator in this kit, and none needed as a separate stage: every ADS-B tool demodulates the 1 Mbps PPM waveform (PHY) and frames/decodes the 112-bit Extended Squitter (LL) together in one pass, so they live at the Capture step. The PHY job here is just a clean capture, a quarter-wave 1090 MHz antenna, ideally a band-pass filter and LNA, into an RTL-SDR. There is no I/Q stage to drive by hand: the decoder correlates the preamble and recovers the bits itself." }, "LL": { - "note": "Receive and decode the ADS-B frames — this is the whole exercise, since the link is plaintext broadcast. Tune 1090 MHz, and the decoder demodulates the PPM bursts, validates the CRC, and reads out DF17/DF18 messages: the 24-bit ICAO address, the callsign, the CPR-encoded position, the velocity. For the US 978 MHz UAT link, run dump978 instead (or as well). The decoder IS the analyst tool here — there is no separate Wireshark/PCAP step; it outputs decoded frames and serves them on Beast/raw/JSON ports for the map and for plausibility checks. Pick dump1090-fa for the classic path, readsb for a modern high-performance receiver, or gr-air-modes to work the signal inside a GNU Radio flowgraph.", + "note": "Receive and decode the ADS-B frames, this is the whole exercise, since the link is plaintext broadcast. Tune 1090 MHz, and the decoder demodulates the PPM bursts, validates the CRC, and reads out DF17/DF18 messages: the 24-bit ICAO address, the callsign, the CPR-encoded position, the velocity. For the US 978 MHz UAT link, run dump978 instead (or as well). The decoder IS the analyst tool here, there is no separate Wireshark/PCAP step; it outputs decoded frames and serves them on Beast/raw/JSON ports for the map and for plausibility checks. Pick dump1090-fa for the classic path, readsb for a modern high-performance receiver, or gr-air-modes to work the signal inside a GNU Radio flowgraph.", "tools": [ { "tool": "dump1090", "role": "Primary 1090ES decoder", "why": "The classic Mode S / ADS-B decoder for RTL-SDR: demodulates the 1090 MHz PPM Extended Squitter, validates CRC and decodes DF17/DF18 (ICAO address, callsign, CPR position, velocity, altitude), with a built-in web map and Beast/raw/JSON output. The de-facto reference receiver and the simplest first decode.", "deps": ["rtl-sdr-v4"] }, { "tool": "readsb", "role": "Modern high-performance decoder", "why": "The actively maintained 'swiss-knife' fork of the dump1090 lineage: decodes 1090ES, tracks many aircraft at once, ingests UAT from dump978, and emits Beast/raw/JSON for downstream maps like tar1090. The default for a permanent or busy receiver.", "deps": ["rtl-sdr-v4"] }, - { "tool": "dump978", "role": "978 MHz UAT decoder", "why": "Decodes the US 978 MHz UAT link used by lower-altitude general aviation — the second ADS-B flavour the 1090 decoders do not cover. Run it alongside dump1090/readsb to see both links; feeds the same maps and aggregators.", "caveat": "US-only link; needs the SDR tuned to 978 MHz (a second dongle to run both links at once).", "deps": ["rtl-sdr-v4"] }, - { "tool": "gr-air-modes", "role": "GNU Radio receiver", "why": "A GNU Radio Mode S / ADS-B flowgraph that demodulates 1090 MHz and decodes the Extended Squitter — the choice when you want the signal inside a flowgraph to see and modify each DSP block rather than use a black-box decoder.", "caveat": "Older codebase (last active ~2021); a learning/DSP receiver rather than a polished aggregator.", "deps": ["rtl-sdr-v4", "hackrf-one", "bladerf-2-micro", "usrp-b210"] } + { "tool": "dump978", "role": "978 MHz UAT decoder", "why": "Decodes the US 978 MHz UAT link used by lower-altitude general aviation, the second ADS-B flavour the 1090 decoders do not cover. Run it alongside dump1090/readsb to see both links; feeds the same maps and aggregators.", "caveat": "US-only link; needs the SDR tuned to 978 MHz (a second dongle to run both links at once).", "deps": ["rtl-sdr-v4"] }, + { "tool": "gr-air-modes", "role": "GNU Radio receiver", "why": "A GNU Radio Mode S / ADS-B flowgraph that demodulates 1090 MHz and decodes the Extended Squitter, the choice when you want the signal inside a flowgraph to see and modify each DSP block rather than use a black-box decoder.", "caveat": "Older codebase (last active ~2021); a learning/DSP receiver rather than a polished aggregator.", "deps": ["rtl-sdr-v4", "hackrf-one", "bladerf-2-micro", "usrp-b210"] } ] }, "CR": { - "note": "There is nothing to decrypt. ADS-B is a plaintext broadcast: the message format and the CPR position encoding are public, so the positions, callsigns and ICAO addresses read at the Capture step are decoded, not cracked — there is no session key (as with BLE pairing) and no handshake (as with WPA) anywhere in the link. The real security problem is the opposite of confidentiality: the link has NO authentication and NO integrity. A receiver has no way to prove a frame came from the aircraft it claims to be from, no signature over the position, and no replay protection. That missing authentication is not a bug you break — it is the design gap that makes the Attack step possible: anything that can transmit a well-formed 1090ES frame is, to every receiver in range, indistinguishable from a real aircraft." + "note": "There is nothing to decrypt. ADS-B is a plaintext broadcast: the message format and the CPR position encoding are public, so the positions, callsigns and ICAO addresses read at the Capture step are decoded, not cracked, there is no session key (as with BLE pairing) and no handshake (as with WPA) anywhere in the link. The real security problem is the opposite of confidentiality: the link has NO authentication and NO integrity. A receiver has no way to prove a frame came from the aircraft it claims to be from, no signature over the position, and no replay protection. That missing authentication is not a bug you break, it is the design gap that makes the Attack step possible: anything that can transmit a well-formed 1090ES frame is, to every receiver in range, indistinguishable from a real aircraft." }, "AT": { - "note": "Because the link is unauthenticated, the attack is to imitate it: transmit forged 1090ES Extended Squitter frames with a chosen ICAO address, callsign and position, and every receiver in range accepts them as a real aircraft — letting you inject ghost aircraft, move an existing track, or flood the picture. This is LEGALLY SENSITIVE: 1090 MHz is protected aviation safety spectrum and transmitting ADS-B affects real air-traffic systems. Do this ONLY as authorized lab/research work over a CONDUCTED (cabled) or SHIELDED (Faraday-enclosure) path into the target receiver — NEVER radiate on-air, under any circumstances. The technique needs a TX-capable SDR; the RTL-SDR is receive-only and cannot transmit. ADSB-Out is a concrete, verifiable encoder for the frame-forging step; the broader 'flood / DoS' and 'replay' variants are configured on the same encode-and-transmit rig rather than a separate program.", + "note": "Because the link is unauthenticated, the attack is to imitate it: transmit forged 1090ES Extended Squitter frames with a chosen ICAO address, callsign and position, and every receiver in range accepts them as a real aircraft, letting you inject ghost aircraft, move an existing track, or flood the picture. This is LEGALLY SENSITIVE: 1090 MHz is protected aviation safety spectrum and transmitting ADS-B affects real air-traffic systems. Do this ONLY as authorized lab/research work over a CONDUCTED (cabled) or SHIELDED (Faraday-enclosure) path into the target receiver, NEVER radiate on-air, under any circumstances. The technique needs a TX-capable SDR; the RTL-SDR is receive-only and cannot transmit. ADSB-Out is a concrete, verifiable encoder for the frame-forging step; the broader 'flood / DoS' and 'replay' variants are configured on the same encode-and-transmit rig rather than a separate program.", "tools": [ - { "tool": "adsb-out", "role": "Frame forging + TX (spoofing/injection)", "why": "A Python encoder that builds forged 1090ES Extended Squitter frames — chosen ICAO address, position, altitude — into an I/Q file you transmit on a TX-capable SDR (HackRF via hackrf_transfer). The concrete demonstration that an unauthenticated link accepts a higher-power forged frame as a genuine aircraft. Author states it is for academic purposes only.", "caveat": "AUTHORIZED, RF-CONTAINED testing only — conducted/shielded path, NEVER radiated on-air (1090 MHz is aviation safety spectrum). RTL-SDR cannot transmit. Stable but inactive (last commit ~2021).", "deps": ["hackrf-one"] } + { "tool": "adsb-out", "role": "Frame forging + TX (spoofing/injection)", "why": "A Python encoder that builds forged 1090ES Extended Squitter frames, chosen ICAO address, position, altitude, into an I/Q file you transmit on a TX-capable SDR (HackRF via hackrf_transfer). The concrete demonstration that an unauthenticated link accepts a higher-power forged frame as a genuine aircraft. Author states it is for academic purposes only.", "caveat": "AUTHORIZED, RF-CONTAINED testing only, conducted/shielded path, NEVER radiated on-air (1090 MHz is aviation safety spectrum). RTL-SDR cannot transmit. Stable but inactive (last commit ~2021).", "deps": ["hackrf-one"] } ] }, "AP": { - "note": "Above the raw frames sits the 'air picture': turning the decoded stream into tracked aircraft, fusing it with other sources, and judging whether what each aircraft asserts is plausible. This is where you read meaning out of the feed and where the link's missing authentication is actually defended — not by attacking an interactive protocol (ADS-B has none; it is one-way broadcast), but by sanity-checking the broadcast. tar1090 renders the decoder's output as a live, interactive map of every tracked aircraft for the human view; pyModeS decodes and interprets message contents in code (CPR position, velocity, BDS registers) so you can run plausibility and anti-spoof checks — impossible kinematics, positions inconsistent across receivers, an ICAO address that should not be airborne. Cross-receiver multilateration (MLAT), which times the same frame at several stations to fix an aircraft independently of what it claims, is the standard anti-spoof cross-check that this layer enables.", + "note": "Above the raw frames sits the 'air picture': turning the decoded stream into tracked aircraft, fusing it with other sources, and judging whether what each aircraft asserts is plausible. This is where you read meaning out of the feed and where the link's missing authentication is actually defended, not by attacking an interactive protocol (ADS-B has none; it is one-way broadcast), but by sanity-checking the broadcast. tar1090 renders the decoder's output as a live, interactive map of every tracked aircraft for the human view; pyModeS decodes and interprets message contents in code (CPR position, velocity, BDS registers) so you can run plausibility and anti-spoof checks, impossible kinematics, positions inconsistent across receivers, an ICAO address that should not be airborne. Cross-receiver multilateration (MLAT), which times the same frame at several stations to fix an aircraft independently of what it claims, is the standard anti-spoof cross-check that this layer enables.", "tools": [ - { "tool": "tar1090", "role": "Air-picture map / fusion view", "why": "Renders the decoded traffic from readsb or dump1090-fa as a live, interactive map with history trails, filtering and per-aircraft detail — the readable 'what is in the sky' view that turns a frame stream into situational awareness and makes anomalous tracks visible.", "caveat": "A front-end, not a decoder: it consumes the JSON a decoder serves, so it bonds to readsb/dump1090 rather than to a radio.", "deps": ["readsb", "dump1090"], "needs": "The JSON/aircraft feed served by readsb (or dump1090-fa) at the Capture step — point tar1090 at that running decoder." }, - { "tool": "pymodes", "role": "Message decode + plausibility checks", "why": "A pure-Python library that decodes Mode S / ADS-B message contents — ICAO address, callsign, CPR airborne/surface position, velocity, Comm-B BDS registers — from hex frames or a streamed feed, so you can interpret the data and code your own anti-spoof / plausibility checks (impossible kinematics, cross-receiver position inconsistency, suspect ICAO addresses).", "deps": ["dump1090", "readsb"], "needs": "A frame source from the Capture step: hex messages, or a live stream from dump1090/readsb over TCP (Beast/raw). It consumes that feed — it has no radio of its own." } + { "tool": "tar1090", "role": "Air-picture map / fusion view", "why": "Renders the decoded traffic from readsb or dump1090-fa as a live, interactive map with history trails, filtering and per-aircraft detail, the readable 'what is in the sky' view that turns a frame stream into situational awareness and makes anomalous tracks visible.", "caveat": "A front-end, not a decoder: it consumes the JSON a decoder serves, so it bonds to readsb/dump1090 rather than to a radio.", "deps": ["readsb", "dump1090"], "needs": "The JSON/aircraft feed served by readsb (or dump1090-fa) at the Capture step, point tar1090 at that running decoder." }, + { "tool": "pymodes", "role": "Message decode + plausibility checks", "why": "A pure-Python library that decodes Mode S / ADS-B message contents, ICAO address, callsign, CPR airborne/surface position, velocity, Comm-B BDS registers, from hex frames or a streamed feed, so you can interpret the data and code your own anti-spoof / plausibility checks (impossible kinematics, cross-receiver position inconsistency, suspect ICAO addresses).", "deps": ["dump1090", "readsb"], "needs": "A frame source from the Capture step: hex messages, or a live stream from dump1090/readsb over TCP (Beast/raw). It consumes that feed, it has no radio of its own." } ] } } diff --git a/src/data/toolchains/btclassic.js b/src/data/toolchains/btclassic.js index ddeba8e..4651928 100644 --- a/src/data/toolchains/btclassic.js +++ b/src/data/toolchains/btclassic.js @@ -1,62 +1,62 @@ export default { status: 'complete', facts: [ - { k: 'Band', v: '2.402–2.480 GHz (2.4 GHz ISM) — 79 RF channels × 1 MHz, adaptive frequency hopping (AFH) at ~1600 hops/s. Sharing the band with BLE and Wi-Fi, but a different PHY/MAC from BLE.' }, + { k: 'Band', v: '2.402 to 2.480 GHz (2.4 GHz ISM), 79 RF channels × 1 MHz, adaptive frequency hopping (AFH) at ~1600 hops/s. Sharing the band with BLE and Wi-Fi, but a different PHY/MAC from BLE.' }, { k: 'Modulation / rate', v: 'Basic Rate (BR): GFSK, 1 Mbps. Enhanced Data Rate (EDR): π/4-DQPSK (2 Mbps) and 8DPSK (3 Mbps). The fast 79-channel hop is what makes BR/EDR hard to follow with a static SDR.' }, { k: 'Identifiers', v: '48-bit BD_ADDR (the device address; upper 24 bits = OUI/vendor) and a Class of Device (CoD) field that hints at the device type. Discoverable devices answer an inquiry scan; non-discoverable ones must be addressed directly.' }, - { k: 'Security', v: 'Legacy pairing: a PIN seeds the link key — short/fixed PINs fall to an offline attack on a captured pairing. Secure Simple Pairing (SSP): ECDH (P-192 in 2.1, P-256 in 4.1+) — but the "Just Works" association model has no MITM protection. Link-layer encryption is E0 (legacy) or AES-CCM. The KNOB attack downgrades the encryption key entropy during negotiation.' }, + { k: 'Security', v: 'Legacy pairing: a PIN seeds the link key, short/fixed PINs fall to an offline attack on a captured pairing. Secure Simple Pairing (SSP): ECDH (P-192 in 2.1, P-256 in 4.1+), but the "Just Works" association model has no MITM protection. Link-layer encryption is E0 (legacy) or AES-CCM. The KNOB attack downgrades the encryption key entropy during negotiation.' }, { k: 'Topology / targets', v: 'Piconet: one master + up to 7 active slaves; services exposed over profiles (SDP, RFCOMM, HID, A2DP/HFP audio, OBEX). Common targets: wireless headsets/speakers, keyboards & mice (HID), car infotainment / hands-free, OBD-II dongles, point-of-sale and industrial gear.' }, ], reference: { name: 'BSAM (Tarlogic)', url: 'https://www.tarlogic.com/bsam/', - note: 'As with BLE, RFSAM owns the RF floors for Bluetooth Classic — getting BR/EDR off the air and into a dissector on cheap hardware — and defers the link-and-above assessment (pairing, profiles, application logic) to Tarlogic’s BSAM, adding only the RF-capture prerequisite. This page is deliberately honest: accessible BR/EDR tooling is thinner and younger than the BLE or Wi-Fi ecosystems, and most of it runs on one $5 board (the original ESP32).', + note: 'As with BLE, RFSAM owns the RF floors for Bluetooth Classic, getting BR/EDR off the air and into a dissector on cheap hardware, and defers the link-and-above assessment (pairing, profiles, application logic) to Tarlogic’s BSAM, adding only the RF-capture prerequisite. This page is deliberately honest: accessible BR/EDR tooling is thinner and younger than the BLE or Wi-Fi ecosystems, and most of it runs on one $5 board (the original ESP32).', }, layers: { IG: { - note: 'Identify the Bluetooth Classic device before any RF work — no capture yet. The first question is whether the device even speaks BR/EDR (Classic) or only BLE: an ESP32-S3, nRF or CC-series target is LE-only, while audio gear, HID peripherals and car/OBD modules are usually Classic or dual-mode. From there, fingerprint the controller SoC and pairing model, because those decide what the rest of this descent can do. Most of this is readable from the FCC ID, a teardown, the BD_ADDR’s vendor OUI, and the Class-of-Device the device advertises when discoverable.', + note: 'Identify the Bluetooth Classic device before any RF work, no capture yet. The first question is whether the device even speaks BR/EDR (Classic) or only BLE: an ESP32-S3, nRF or CC-series target is LE-only, while audio gear, HID peripherals and car/OBD modules are usually Classic or dual-mode. From there, fingerprint the controller SoC and pairing model, because those decide what the rest of this descent can do. Most of this is readable from the FCC ID, a teardown, the BD_ADDR’s vendor OUI, and the Class-of-Device the device advertises when discoverable.', lookFor: [ - 'Bluetooth mode — Classic (BR/EDR), dual-mode (BR/EDR + LE), or LE-only. Only BR/EDR belongs on this page; LE-only devices go to the BLE descent.', - 'Controller SoC / firmware (FCC ID, teardown, BD_ADDR OUI) — cross-reference Bluetooth Classic advisories: BlueBorne, KNOB (key-size downgrade), and the BrakTooth family (baseband/LMP crashes and RCE across many BR/EDR controllers).', + 'Bluetooth mode, Classic (BR/EDR), dual-mode (BR/EDR + LE), or LE-only. Only BR/EDR belongs on this page; LE-only devices go to the BLE descent.', + 'Controller SoC / firmware (FCC ID, teardown, BD_ADDR OUI), cross-reference Bluetooth Classic advisories: BlueBorne, KNOB (key-size downgrade), and the BrakTooth family (baseband/LMP crashes and RCE across many BR/EDR controllers).', 'BD_ADDR and Class of Device (CoD): the 48-bit address and the device-type hint, readable from any inquiry response while the device is discoverable.', - 'Discoverability — is the device in inquiry-scan mode (answers a scan) or non-discoverable (you must already know its BD_ADDR)?', - 'Pairing / association model: legacy PIN pairing vs Secure Simple Pairing (and within SSP, Just Works vs Passkey vs OOB) — and whether the link is encrypted (E0 vs AES-CCM).', - 'Exposed profiles/services (SDP browse): RFCOMM serial, HID, A2DP/HFP audio, OBEX object push — the application surface above the link.', + 'Discoverability, is the device in inquiry-scan mode (answers a scan) or non-discoverable (you must already know its BD_ADDR)?', + 'Pairing / association model: legacy PIN pairing vs Secure Simple Pairing (and within SSP, Just Works vs Passkey vs OOB), and whether the link is encrypted (E0 vs AES-CCM).', + 'Exposed profiles/services (SDP browse): RFCOMM serial, HID, A2DP/HFP audio, OBEX object push, the application surface above the link.', ], }, SP: { - note: 'Confirm the device is transmitting and enumerate what is reachable. Two complementary moves. First, a spectrum view: BR/EDR hops across all 79 channels ~1600 times a second, so a waterfall over 2.402–2.480 GHz shows band activity but you cannot lock to a single channel the way you can with a fixed-channel protocol — it confirms "something Bluetooth is busy here", not a clean per-packet read. Second, an inquiry scan: cheap ESP32 firmware uses the chip’s own Bluetooth controller to run a true BR/EDR inquiry and list every discoverable device’s BD_ADDR, name, RSSI and Class of Device — the BR/EDR analogue of a BLE advertising scan, and usually the most useful "see it" step for Classic.', + note: 'Confirm the device is transmitting and enumerate what is reachable. Two complementary moves. First, a spectrum view: BR/EDR hops across all 79 channels ~1600 times a second, so a waterfall over 2.402 to 2.480 GHz shows band activity but you cannot lock to a single channel the way you can with a fixed-channel protocol, it confirms "something Bluetooth is busy here", not a clean per-packet read. Second, an inquiry scan: cheap ESP32 firmware uses the chip’s own Bluetooth controller to run a true BR/EDR inquiry and list every discoverable device’s BD_ADDR, name, RSSI and Class of Device, the BR/EDR analogue of a BLE advertising scan, and usually the most useful "see it" step for Classic.', tools: [ - { tool: 'gqrx', role: 'Spectrum / waterfall view', why: 'Watch 2.402–2.480 GHz for the hopping BR/EDR bursts — confirm the device is alive and the band is busy. You see activity, not clean per-packet decode: the 1600 hops/s frustrate a static SDR.', caveat: 'Activity view only — fast AFH hopping means an SDR cannot follow a piconet packet-by-packet here.', deps: ['hackrf-one', 'bladerf-2-micro'] }, - { tool: 'esp32-classic-bt-scan', role: 'BR/EDR inquiry scan', why: 'Runs a true Bluetooth Classic inquiry on the ESP32’s own controller and lists each discoverable device’s BD_ADDR, name, RSSI and Class of Device — the cheapest way to enumerate Classic devices in range.', caveat: 'Only finds devices currently in discoverable / inquiry-scan mode; needs the original ESP32 (Classic radio), not an S3/C-series.', deps: ['esp32-devkit'] }, - { tool: 'esp32-bt-exp', role: 'Dual-mode discovery dump', why: 'Brings up the Bluedroid stack in dual-mode and dumps both Classic (inquiry) and BLE devices it sees — a quick combined survey when a target may be either.', caveat: 'Discovery only — no pairing or connection. Classic discovery needs the BR/EDR-capable original ESP32.', deps: ['esp32-devkit'] }, + { tool: 'gqrx', role: 'Spectrum / waterfall view', why: 'Watch 2.402 to 2.480 GHz for the hopping BR/EDR bursts, confirm the device is alive and the band is busy. You see activity, not clean per-packet decode: the 1600 hops/s frustrate a static SDR.', caveat: 'Activity view only, fast AFH hopping means an SDR cannot follow a piconet packet-by-packet here.', deps: ['hackrf-one', 'bladerf-2-micro'] }, + { tool: 'esp32-classic-bt-scan', role: 'BR/EDR inquiry scan', why: 'Runs a true Bluetooth Classic inquiry on the ESP32’s own controller and lists each discoverable device’s BD_ADDR, name, RSSI and Class of Device, the cheapest way to enumerate Classic devices in range.', caveat: 'Only finds devices currently in discoverable / inquiry-scan mode; needs the original ESP32 (Classic radio), not an S3/C-series.', deps: ['esp32-devkit'] }, + { tool: 'esp32-bt-exp', role: 'Dual-mode discovery dump', why: 'Brings up the Bluedroid stack in dual-mode and dumps both Classic (inquiry) and BLE devices it sees, a quick combined survey when a target may be either.', caveat: 'Discovery only, no pairing or connection. Classic discovery needs the BR/EDR-capable original ESP32.', deps: ['esp32-devkit'] }, ], }, PHY: { note: 'No standalone BR/EDR demodulator in this kit. Decoding live GFSK/DQPSK while it hops 1600 times a second is impractical for a software-defined radio, so the practical capture path does PHY and framing together inside a device that owns a real Bluetooth controller. The ESP32 BR/EDR sniffer takes exactly this route: it patches the chip’s own baseband firmware to expose the packets the controller already demodulates, rather than trying to recover them from raw I/Q.', }, LL: { - note: 'Capture and decode Bluetooth Classic frames. Because an SDR cannot follow the hop, the accessible capture path uses a device with its own BR/EDR radio. The reference option is the ESP32 Classic sniffer: patched ROM firmware dumps baseband packets (BT header, channel, role, FHS, ACL and LMP) over USB serial into a Python host tool with Scapy/Wireshark output — serious BR/EDR visibility on a $5 board, though it actively connects to the target. The Ubertooth One can also pick up some Basic-Rate Classic, a legacy budget option. Either way you export to Wireshark for dissection.', + note: 'Capture and decode Bluetooth Classic frames. Because an SDR cannot follow the hop, the accessible capture path uses a device with its own BR/EDR radio. The reference option is the ESP32 Classic sniffer: patched ROM firmware dumps baseband packets (BT header, channel, role, FHS, ACL and LMP) over USB serial into a Python host tool with Scapy/Wireshark output, serious BR/EDR visibility on a $5 board, though it actively connects to the target. The Ubertooth One can also pick up some Basic-Rate Classic, a legacy budget option. Either way you export to Wireshark for dissection.', decoder: 'wireshark', tools: [ - { tool: 'esp32-bt-classic-sniffer', role: 'BR/EDR baseband sniffer', why: 'Patches the ESP32 Bluetooth ROM stack to dump baseband packets — BT header, channel, role, FHS, ACL and LMP — over USB serial to a host Python tool (BTSnifferBREDR.py) with Scapy and Wireshark output. The accessible reference BR/EDR capture path on commodity hardware.', caveat: 'Actively connects to the target to follow it (not purely passive); authorised testing only. Needs the original ESP32 (Classic radio).', deps: ['esp32-devkit'] }, - { tool: 'ubertooth-tools', role: 'Budget Basic-Rate capture', why: 'The Ubertooth One can capture some Basic-Rate Bluetooth Classic in addition to its BLE work — a legacy, lower-fidelity option when an ESP32 sniffer is not to hand.', caveat: 'Partial Basic-Rate only; weaker and dated next to the ESP32 baseband sniffer for serious BR/EDR work.', deps: ['ubertooth-one'] }, + { tool: 'esp32-bt-classic-sniffer', role: 'BR/EDR baseband sniffer', why: 'Patches the ESP32 Bluetooth ROM stack to dump baseband packets, BT header, channel, role, FHS, ACL and LMP, over USB serial to a host Python tool (BTSnifferBREDR.py) with Scapy and Wireshark output. The accessible reference BR/EDR capture path on commodity hardware.', caveat: 'Actively connects to the target to follow it (not purely passive); authorised testing only. Needs the original ESP32 (Classic radio).', deps: ['esp32-devkit'] }, + { tool: 'ubertooth-tools', role: 'Budget Basic-Rate capture', why: 'The Ubertooth One can capture some Basic-Rate Bluetooth Classic in addition to its BLE work, a legacy, lower-fidelity option when an ESP32 sniffer is not to hand.', caveat: 'Partial Basic-Rate only; weaker and dated next to the ESP32 baseband sniffer for serious BR/EDR work.', deps: ['ubertooth-one'] }, ], }, CR: { - note: 'Be honest about what is breakable. Legacy PIN pairing is the classic weakness: the PIN seeds the link key, so a captured legacy pairing exchange with a short or fixed PIN (0000 / 1234) falls to an offline brute force that recovers the link key and decrypts the session — but you must have captured the pairing, and modern devices rarely use legacy pairing. Secure Simple Pairing (ECDH, P-192/P-256) resists offline key recovery; its weak point is the "Just Works" association model (no MITM protection), an active-MITM problem rather than an offline crack. The KNOB attack is a separate, protocol-level flaw: it negotiates the encryption key down to as little as 1 byte of entropy, after which the key is brute-forceable — a downgrade, not a maths break. There is no clean point-and-click ESP32 tool for these on cheap hardware, so this floor is mostly analysis of a capture from the previous step plus the BSAM pairing controls.', + note: 'Be honest about what is breakable. Legacy PIN pairing is the classic weakness: the PIN seeds the link key, so a captured legacy pairing exchange with a short or fixed PIN (0000 / 1234) falls to an offline brute force that recovers the link key and decrypts the session, but you must have captured the pairing, and modern devices rarely use legacy pairing. Secure Simple Pairing (ECDH, P-192/P-256) resists offline key recovery; its weak point is the "Just Works" association model (no MITM protection), an active-MITM problem rather than an offline crack. The KNOB attack is a separate, protocol-level flaw: it negotiates the encryption key down to as little as 1 byte of entropy, after which the key is brute-forceable, a downgrade, not a maths break. There is no clean point-and-click ESP32 tool for these on cheap hardware, so this floor is mostly analysis of a capture from the previous step plus the BSAM pairing controls.', }, AT: { - note: 'Going active against Bluetooth Classic means transmitting in the 2.4 GHz ISM band and poking a live BR/EDR device — authorised testing only, on devices you own or are contracted to assess. The standout accessible capability is BrakTooth: a PoC suite of baseband/LMP attacks (≈16 CVEs, 20+ variants) that crash, deadlock or in some cases run code on the BR/EDR controllers of dozens of SoCs — and it runs on the same $5 ESP32. Beyond that, the KNOB key-entropy downgrade enables a follow-on brute force where supported, and a broadband 2.4 GHz jammer denies the band wholesale (illegal in most jurisdictions outside a shielded lab). Forging/replaying valid encrypted frames needs the link key from the previous step.', + note: 'Going active against Bluetooth Classic means transmitting in the 2.4 GHz ISM band and poking a live BR/EDR device, authorised testing only, on devices you own or are contracted to assess. The standout accessible capability is BrakTooth: a PoC suite of baseband/LMP attacks (≈16 CVEs, 20+ variants) that crash, deadlock or in some cases run code on the BR/EDR controllers of dozens of SoCs, and it runs on the same $5 ESP32. Beyond that, the KNOB key-entropy downgrade enables a follow-on brute force where supported, and a broadband 2.4 GHz jammer denies the band wholesale (illegal in most jurisdictions outside a shielded lab). Forging/replaying valid encrypted frames needs the link key from the previous step.', tools: [ - { tool: 'braktooth', role: 'Baseband / LMP exploit & fuzz', why: 'The public BrakTooth release: fuzzes and fires ~20 baseband/LMP attack variants (≈16 CVEs) at a target BR/EDR controller — crash, deadlock and, on some chips, RCE — from a cheap ESP32. The reference accessible BR/EDR attack framework.', caveat: 'Crash/DoS and in some cases RCE against live targets — authorised testing only. Patch status varies by vendor; treat the CVE list as representative, not current.', deps: ['esp32-devkit'] }, - { tool: 'esp32-bluejammer', role: 'Broadband 2.4 GHz jam (DoS)', why: 'Floods all of 2.4 GHz with noise to deny Bluetooth Classic (79 ch), BLE and Wi-Fi at once — a wholesale availability test of how a piconet behaves under RF denial.', caveat: 'RF jamming is illegal in most jurisdictions (e.g. unlawful in the US under FCC rules) — authorised testing only, in an RF-shielded / controlled environment. Needs two nRF24L01+PA+LNA modules.', deps: ['esp32-devkit'], needs: 'Two nRF24L01+PA+LNA modules wired to the ESP32.' }, + { tool: 'braktooth', role: 'Baseband / LMP exploit & fuzz', why: 'The public BrakTooth release: fuzzes and fires ~20 baseband/LMP attack variants (≈16 CVEs) at a target BR/EDR controller, crash, deadlock and, on some chips, RCE, from a cheap ESP32. The reference accessible BR/EDR attack framework.', caveat: 'Crash/DoS and in some cases RCE against live targets, authorised testing only. Patch status varies by vendor; treat the CVE list as representative, not current.', deps: ['esp32-devkit'] }, + { tool: 'esp32-bluejammer', role: 'Broadband 2.4 GHz jam (DoS)', why: 'Floods all of 2.4 GHz with noise to deny Bluetooth Classic (79 ch), BLE and Wi-Fi at once, a wholesale availability test of how a piconet behaves under RF denial.', caveat: 'RF jamming is illegal in most jurisdictions (e.g. unlawful in the US under FCC rules), authorised testing only, in an RF-shielded / controlled environment. Needs two nRF24L01+PA+LNA modules.', deps: ['esp32-devkit'], needs: 'Two nRF24L01+PA+LNA modules wired to the ESP32.' }, ], }, AP: { - note: 'Above the link sits the application — the profiles and services the device exposes over its BR/EDR link: SDP (the service directory), RFCOMM serial channels (often carrying AT commands on hands-free/car units), HID (inject keystrokes into a host that trusts the device), A2DP/HFP audio, and OBEX object push. The practical driver here is a normal Linux host with its BlueZ stack over any standard USB Bluetooth adapter: `sdptool browse` to enumerate services, `l2ping` to probe reachability, `bluetoothctl` to pair and connect, and profile tools (obexftp, HID/HFP utilities) to exercise what the device trusts — the same host workflow BSAM’s Bluetooth controls assume.', + note: 'Above the link sits the application, the profiles and services the device exposes over its BR/EDR link: SDP (the service directory), RFCOMM serial channels (often carrying AT commands on hands-free/car units), HID (inject keystrokes into a host that trusts the device), A2DP/HFP audio, and OBEX object push. The practical driver here is a normal Linux host with its BlueZ stack over any standard USB Bluetooth adapter: `sdptool browse` to enumerate services, `l2ping` to probe reachability, `bluetoothctl` to pair and connect, and profile tools (obexftp, HID/HFP utilities) to exercise what the device trusts, the same host workflow BSAM’s Bluetooth controls assume.', tools: [ - { tool: 'usb-bt-dongle', role: 'Host BR/EDR stack (BlueZ)', why: 'A standard USB Bluetooth adapter gives a Linux host its BR/EDR controller; from there BlueZ drives the application layer — enumerate services, probe, pair and exercise RFCOMM/HID/OBEX profiles.', caveat: 'A legitimate host stack, not a covert injector — most application-layer testing requires pairing/permission with the target.', deps: [], needs: 'A Linux host running BlueZ: sdptool browse (service discovery), l2ping (reachability), bluetoothctl (pair/connect), and profile tools such as obexftp.' }, + { tool: 'usb-bt-dongle', role: 'Host BR/EDR stack (BlueZ)', why: 'A standard USB Bluetooth adapter gives a Linux host its BR/EDR controller; from there BlueZ drives the application layer, enumerate services, probe, pair and exercise RFCOMM/HID/OBEX profiles.', caveat: 'A legitimate host stack, not a covert injector, most application-layer testing requires pairing/permission with the target.', deps: [], needs: 'A Linux host running BlueZ: sdptool browse (service discovery), l2ping (reachability), bluetoothctl (pair/connect), and profile tools such as obexftp.' }, ], }, }, diff --git a/src/data/toolchains/gnss.js b/src/data/toolchains/gnss.js index 841f740..89d6c92 100644 --- a/src/data/toolchains/gnss.js +++ b/src/data/toolchains/gnss.js @@ -4,51 +4,51 @@ export default { { "k": "Band", "v": "L-band. GPS L1 1575.42 MHz · L2 1227.60 MHz · L5 1176.45 MHz. Neighbours: GLONASS L1 ~1602 MHz, Galileo E1 1575.42 MHz (overlaps GPS L1), BeiDou B1 1561.098 MHz." }, { "k": "Signal (GPS L1 C/A)", "v": "BPSK on a 1575.42 MHz carrier; 1023-chip C/A spreading code at 1.023 Mcps, repeating every 1 ms; navigation message at 50 bps. One PRN code per satellite (CDMA)." }, { "k": "Constellations", "v": "GPS (US) · GLONASS (RU) · Galileo (EU) · BeiDou (CN), plus regional QZSS/NavIC. A receiver needs 4+ satellites in view to solve position and time." }, - { "k": "Security", "v": "Civilian signals (GPS C/A, GLONASS, BeiDou B1, Galileo E1 OS) are UNENCRYPTED and UNAUTHENTICATED — the signal structure is public and any receiver decodes it. Military P(Y)/M-code is encrypted but out of scope. Galileo OSNMA adds optional message authentication; legacy GPS C/A has none." }, - { "k": "Power at receiver", "v": "Extremely weak — about -125 to -130 dBm, below the thermal noise floor; recovered only by despreading the known PRN code. This is why an attacker's slightly stronger signal can capture a receiver." } + { "k": "Security", "v": "Civilian signals (GPS C/A, GLONASS, BeiDou B1, Galileo E1 OS) are UNENCRYPTED and UNAUTHENTICATED, the signal structure is public and any receiver decodes it. Military P(Y)/M-code is encrypted but out of scope. Galileo OSNMA adds optional message authentication; legacy GPS C/A has none." }, + { "k": "Power at receiver", "v": "Extremely weak, about -125 to -130 dBm, below the thermal noise floor; recovered only by despreading the known PRN code. This is why an attacker's slightly stronger signal can capture a receiver." } ], "reference": null, "layers": { "IG": { - "note": "Work out what GNSS the target consumes before touching the air — there is no capture yet. Most receivers track several constellations at once on L1, and some add L2/L5 for accuracy. The defining fact for security work: civilian signals carry no encryption and no authentication, so the entire attack surface is the receiver's trust in whatever signal it hears, not any secret it holds. Identify which bands/constellations the target uses, whether it has any spoofing/jamming mitigations, and how it behaves when the fix is lost.", + "note": "Work out what GNSS the target consumes before touching the air, there is no capture yet. Most receivers track several constellations at once on L1, and some add L2/L5 for accuracy. The defining fact for security work: civilian signals carry no encryption and no authentication, so the entire attack surface is the receiver's trust in whatever signal it hears, not any secret it holds. Identify which bands/constellations the target uses, whether it has any spoofing/jamming mitigations, and how it behaves when the fix is lost.", "lookFor": [ - "Which constellations and bands the receiver tracks (GPS-only L1, or multi-constellation, or multi-band L1/L2/L5) — this sets which frequencies you survey and which signal you must synthesise to move it.", - "That civilian signals are unauthenticated: GPS L1 C/A, GLONASS, BeiDou B1 and Galileo E1 OS are public, unencrypted spreading codes — there is no key to recover and no credential to forge, only a signal to imitate.", - "Receiver chipset / module (FCC ID, teardown, NMEA vendor strings) — cross-reference known weaknesses and whether it implements any anti-spoof (RAIM, consistency checks) or anti-jam features. The fastest read on a real module is its own output: plug a u-blox NEO-class USB/serial receiver in and watch the NMEA sentences (GGA/RMC/GSV) and UBX messages it emits to see the constellations, satellite count and fix quality directly.", - "What the device does with time and position downstream (navigation, timestamping, a timing/PPS reference for a network or power grid) — this is what a spoof or jam actually disrupts.", + "Which constellations and bands the receiver tracks (GPS-only L1, or multi-constellation, or multi-band L1/L2/L5), this sets which frequencies you survey and which signal you must synthesise to move it.", + "That civilian signals are unauthenticated: GPS L1 C/A, GLONASS, BeiDou B1 and Galileo E1 OS are public, unencrypted spreading codes, there is no key to recover and no credential to forge, only a signal to imitate.", + "Receiver chipset / module (FCC ID, teardown, NMEA vendor strings), cross-reference known weaknesses and whether it implements any anti-spoof (RAIM, consistency checks) or anti-jam features. The fastest read on a real module is its own output: plug a u-blox NEO-class USB/serial receiver in and watch the NMEA sentences (GGA/RMC/GSV) and UBX messages it emits to see the constellations, satellite count and fix quality directly.", + "What the device does with time and position downstream (navigation, timestamping, a timing/PPS reference for a network or power grid), this is what a spoof or jam actually disrupts.", "Whether it consumes any authenticated signal (Galileo OSNMA) or assistance data (A-GNSS) that changes the trust model.", - "Behaviour on signal loss: does it coast, alarm, or silently accept the first plausible fix it reacquires — the latter is what a spoofer exploits." + "Behaviour on signal loss: does it coast, alarm, or silently accept the first plausible fix it reacquires, the latter is what a spoofer exploits." ] }, "SP": { - "note": "Confirm the L-band signal is actually present and judge the RF environment before you try to decode or attack it. GNSS sits around 1.2–1.6 GHz, so any SDR that reaches L1 (1575.42 MHz) can look — but the signal is buried below the noise floor, so on a waterfall you are not looking for the GNSS signal itself (you will not see it) but for what is wrong: a strong carrier or wideband hump on top of L1 means interference or a jammer; a clean, quiet band means a healthy environment. This step also sizes up the local RF: a jamming/interference survey before fieldwork, and a check that your active antenna and bias-tee are feeding signal. A standard GPS receiver module is the cheap complement here: its satellite-view and C/N0 numbers (via gpsd's gpsmon/cgps or u-center) tell you, satellite by satellite, whether the band is healthy or being drowned out — the receiver's-eye view that a waterfall alone cannot give.", + "note": "Confirm the L-band signal is actually present and judge the RF environment before you try to decode or attack it. GNSS sits around 1.2 to 1.6 GHz, so any SDR that reaches L1 (1575.42 MHz) can look, but the signal is buried below the noise floor, so on a waterfall you are not looking for the GNSS signal itself (you will not see it) but for what is wrong: a strong carrier or wideband hump on top of L1 means interference or a jammer; a clean, quiet band means a healthy environment. This step also sizes up the local RF: a jamming/interference survey before fieldwork, and a check that your active antenna and bias-tee are feeding signal. A standard GPS receiver module is the cheap complement here: its satellite-view and C/N0 numbers (via gpsd's gpsmon/cgps or u-center) tell you, satellite by satellite, whether the band is healthy or being drowned out, the receiver's-eye view that a waterfall alone cannot give.", "tools": [ - { "tool": "gqrx", "role": "Spectrum / interference survey", "why": "Tune to L1 (1575.42 MHz) and watch the waterfall to confirm a clean band and spot interference or jamming — a strong carrier or wideband energy over L1 is the tell, since the GNSS signal itself sits below the noise floor.", "caveat": "Cannot show the despread GNSS signal — it only reveals interference, carriers and noise. Needs an active GPS antenna; on the RTL-SDR enable the bias-tee to power it.", "deps": ["hackrf-one", "bladerf-2-micro", "usrp-b210", "rtl-sdr-v4"] } + { "tool": "gqrx", "role": "Spectrum / interference survey", "why": "Tune to L1 (1575.42 MHz) and watch the waterfall to confirm a clean band and spot interference or jamming, a strong carrier or wideband energy over L1 is the tell, since the GNSS signal itself sits below the noise floor.", "caveat": "Cannot show the despread GNSS signal, it only reveals interference, carriers and noise. Needs an active GPS antenna; on the RTL-SDR enable the bias-tee to power it.", "deps": ["hackrf-one", "bladerf-2-micro", "usrp-b210", "rtl-sdr-v4"] } ] }, "PHY": { - "note": "No standalone GNSS demodulator in this kit, and two ways the despreading actually happens. With a standard GPS receiver module the satellite's 1.023 Mcps PRN code is correlated inside the chip's own hardware — you never touch the waveform, you just read the NMEA/UBX it emits. With an SDR the same despreading is done in software at Capture: BPSK recovered together with the navigation bits inside the software receiver. Either way there is no point staring at the raw waveform: at about -128 dBm the signal is below the noise floor until something correlates against the known code." + "note": "No standalone GNSS demodulator in this kit, and two ways the despreading actually happens. With a standard GPS receiver module the satellite's 1.023 Mcps PRN code is correlated inside the chip's own hardware, you never touch the waveform, you just read the NMEA/UBX it emits. With an SDR the same despreading is done in software at Capture: BPSK recovered together with the navigation bits inside the software receiver. Either way there is no point staring at the raw waveform: at about -128 dBm the signal is below the noise floor until something correlates against the known code." }, "LL": { - "note": "Receive and read out a live GNSS signal. There are two paths. The EVERYDAY path is a standard GPS/GNSS receiver module (a u-blox NEO over USB/serial): the chip acquires, tracks and solves the fix itself and streams plain NMEA 0183 sentences (plus binary UBX), which you read with gpsd (gpsmon/cgps) or u-center — no SDR, no signal processing on your side. The SDR path instead feeds raw L-band I/Q into a software receiver (GNSS-SDR) that does the acquisition/tracking/decoding itself and outputs the same kind of PVT fix (plus NMEA/RINEX). There is no Wireshark step on either path — the receiver (chip or software) is both demodulator and decoder, and its output is a position/time solution, not a packet capture. The everyday path is how most devices get GPS and the quickest way to see what a receiver actually reports; the SDR path is for when you need the raw I/Q (to feed analysis, or to mirror what you will later spoof). An active GPS antenna helps both; the SDR path additionally needs bias-tee power because the signal is so weak.", + "note": "Receive and read out a live GNSS signal. There are two paths. The EVERYDAY path is a standard GPS/GNSS receiver module (a u-blox NEO over USB/serial): the chip acquires, tracks and solves the fix itself and streams plain NMEA 0183 sentences (plus binary UBX), which you read with gpsd (gpsmon/cgps) or u-center, no SDR, no signal processing on your side. The SDR path instead feeds raw L-band I/Q into a software receiver (GNSS-SDR) that does the acquisition/tracking/decoding itself and outputs the same kind of PVT fix (plus NMEA/RINEX). There is no Wireshark step on either path, the receiver (chip or software) is both demodulator and decoder, and its output is a position/time solution, not a packet capture. The everyday path is how most devices get GPS and the quickest way to see what a receiver actually reports; the SDR path is for when you need the raw I/Q (to feed analysis, or to mirror what you will later spoof). An active GPS antenna helps both; the SDR path additionally needs bias-tee power because the signal is so weak.", "tools": [ - { "tool": "gpsd", "role": "Read a real GPS receiver (NMEA/UBX)", "why": "The normal way to consume a GPS receiver: gpsd reads the NMEA 0183 / UBX stream off the module's serial/USB port and re-serves the fix, while gpsmon and cgps show the live position, satellites and raw sentences in a terminal. The fastest 'see what the receiver reports' path — no SDR, no correlation to run yourself.", "caveat": "Reports only what the receiver chip decides to output; you cannot see the raw I/Q or below the chip's own processing. Linux/BSD (u-center covers the same on Windows).", "deps": ["ublox-neo-gps"] }, - { "tool": "u-center", "role": "Inspect raw NMEA/UBX (GUI)", "why": "u-blox's evaluation GUI: connect to the module and watch every NMEA and UBX message, the satellite view, C/N0 levels and the live fix — the clearest window into exactly what a u-blox receiver is reporting, and it can reconfigure the module too.", "caveat": "Proprietary and Windows-native (u-center 2 for newer modules); u-blox receivers only.", "deps": ["ublox-neo-gps"] }, + { "tool": "gpsd", "role": "Read a real GPS receiver (NMEA/UBX)", "why": "The normal way to consume a GPS receiver: gpsd reads the NMEA 0183 / UBX stream off the module's serial/USB port and re-serves the fix, while gpsmon and cgps show the live position, satellites and raw sentences in a terminal. The fastest 'see what the receiver reports' path, no SDR, no correlation to run yourself.", "caveat": "Reports only what the receiver chip decides to output; you cannot see the raw I/Q or below the chip's own processing. Linux/BSD (u-center covers the same on Windows).", "deps": ["ublox-neo-gps"] }, + { "tool": "u-center", "role": "Inspect raw NMEA/UBX (GUI)", "why": "u-blox's evaluation GUI: connect to the module and watch every NMEA and UBX message, the satellite view, C/N0 levels and the live fix, the clearest window into exactly what a u-blox receiver is reporting, and it can reconfigure the module too.", "caveat": "Proprietary and Windows-native (u-center 2 for newer modules); u-blox receivers only.", "deps": ["ublox-neo-gps"] }, { "tool": "gnss-sdr", "role": "Software GNSS receiver (SDR path)", "why": "The reference open SDR receiver: acquire, track, decode the navigation message and compute a PVT fix from live L1 (and L2/L5) for GPS, Galileo, GLONASS and BeiDou. Use it when you want the raw I/Q path rather than a black-box module. Outputs position/time plus NMEA/RINEX/KML.", "caveat": "Needs an active GPS antenna and bias-tee power; correlation is CPU-intensive. RTL-SDR works for L1 but its ~2.4 MHz bandwidth and 8-bit ADC limit it to single-band C/A.", "deps": ["rtl-sdr-v4", "hackrf-one", "bladerf-2-micro", "usrp-b210"] } ] }, "CR": { - "note": "There is no crypto to break. Civilian GNSS signals — GPS L1 C/A, GLONASS, BeiDou B1, Galileo E1 OS — are unencrypted and unauthenticated by design: the spreading codes and message format are published, so any receiver can decode them and, equally, anyone can generate them. There is no session key to recover (as with BLE pairing) and no handshake to crack (as with WPA). The encrypted military P(Y)/M-codes are out of scope. The real resilience question is not confidentiality but trust: can the receiver tell a genuine satellite signal from a spoofed one? The industry answer is signal authentication — Galileo OSNMA cryptographically signs the navigation message, and modern receivers add consistency/RAIM checks — but legacy GPS C/A offers none, which is exactly why the Attack step works." + "note": "There is no crypto to break. Civilian GNSS signals, GPS L1 C/A, GLONASS, BeiDou B1, Galileo E1 OS, are unencrypted and unauthenticated by design: the spreading codes and message format are published, so any receiver can decode them and, equally, anyone can generate them. There is no session key to recover (as with BLE pairing) and no handshake to crack (as with WPA). The encrypted military P(Y)/M-codes are out of scope. The real resilience question is not confidentiality but trust: can the receiver tell a genuine satellite signal from a spoofed one? The industry answer is signal authentication, Galileo OSNMA cryptographically signs the navigation message, and modern receivers add consistency/RAIM checks, but legacy GPS C/A offers none, which is exactly why the Attack step works." }, "AT": { - "note": "Because the signal is unauthenticated, the attack is to imitate it. Two families, both AUTHORIZED and RF-CONTAINED testing only — transmitting GPS over the air is illegal in most jurisdictions, so work inside a shielded enclosure or over a cabled (conducted) path into the target receiver. SPOOFING synthesises a valid-looking GPS L1 C/A signal at higher power than the real satellites so the receiver locks onto it, letting you drag its reported position or clock to attacker-chosen values. JAMMING simply floods L1 with noise/carrier to deny any fix — useful for resilience testing of how the target degrades. Each technique names the TX-capable SDR it runs on (RTL-SDR is receive-only and cannot transmit).", + "note": "Because the signal is unauthenticated, the attack is to imitate it. Two families, both AUTHORIZED and RF-CONTAINED testing only, transmitting GPS over the air is illegal in most jurisdictions, so work inside a shielded enclosure or over a cabled (conducted) path into the target receiver. SPOOFING synthesises a valid-looking GPS L1 C/A signal at higher power than the real satellites so the receiver locks onto it, letting you drag its reported position or clock to attacker-chosen values. JAMMING simply floods L1 with noise/carrier to deny any fix, useful for resilience testing of how the target degrades. Each technique names the TX-capable SDR it runs on (RTL-SDR is receive-only and cannot transmit).", "tools": [ - { "tool": "gps-sdr-sim", "role": "GPS spoofing (signal synthesis + TX)", "why": "Generates a GPS L1 C/A baseband from a RINEX ephemeris and a chosen static or moving track, then you transmit it on a TX-capable SDR; at higher power than the live sky it captures the receiver and moves its position/time. The canonical demonstration that unauthenticated C/A is trivially imitable.", "caveat": "RF-CONTAINED only (shielded/cabled) — over-the-air GPS TX is illegal. Half-duplex SDRs transmit; RTL-SDR cannot. Modern multi-constellation or OSNMA-aware receivers may detect or reject a single-constellation GPS-only spoof.", "deps": ["hackrf-one", "bladerf-2-micro", "usrp-b210"] }, - { "tool": "gqrx", "role": "Jamming-resilience survey", "why": "Before and during a jamming-resilience test, watch L1 to confirm the interference you are injecting and observe how it sits over the band — the receiver-side counterpart to seeing whether the target loses its fix.", "caveat": "Observation only — gqrx does not transmit. The jamming source itself is a TX-capable SDR driving a carrier/noise into the contained setup; gqrx just monitors it.", "deps": ["hackrf-one", "bladerf-2-micro", "usrp-b210"] } + { "tool": "gps-sdr-sim", "role": "GPS spoofing (signal synthesis + TX)", "why": "Generates a GPS L1 C/A baseband from a RINEX ephemeris and a chosen static or moving track, then you transmit it on a TX-capable SDR; at higher power than the live sky it captures the receiver and moves its position/time. The canonical demonstration that unauthenticated C/A is trivially imitable.", "caveat": "RF-CONTAINED only (shielded/cabled), over-the-air GPS TX is illegal. Half-duplex SDRs transmit; RTL-SDR cannot. Modern multi-constellation or OSNMA-aware receivers may detect or reject a single-constellation GPS-only spoof.", "deps": ["hackrf-one", "bladerf-2-micro", "usrp-b210"] }, + { "tool": "gqrx", "role": "Jamming-resilience survey", "why": "Before and during a jamming-resilience test, watch L1 to confirm the interference you are injecting and observe how it sits over the band, the receiver-side counterpart to seeing whether the target loses its fix.", "caveat": "Observation only, gqrx does not transmit. The jamming source itself is a TX-capable SDR driving a carrier/noise into the contained setup; gqrx just monitors it.", "deps": ["hackrf-one", "bladerf-2-micro", "usrp-b210"] } ] }, "AP": { - "note": "There is no application layer to attack over the air. A civilian GNSS signal is one-way broadcast: satellites transmit, receivers listen, and there is no uplink, no session and no per-receiver protocol to interact with — so the BLE/Wi-Fi notion of probing what the device trusts above the link does not apply on the RF side. Everything an attacker can influence is already decided at the signal level (Attack): once you control the position and time the receiver derives, you control every downstream system that trusts them — navigation, geofencing, timestamps, a PPS timing reference. The application-layer impact is therefore assessed in the victim system (does a false position/time cause unsafe behaviour?), not by attacking a GNSS protocol that has no interactive surface." + "note": "There is no application layer to attack over the air. A civilian GNSS signal is one-way broadcast: satellites transmit, receivers listen, and there is no uplink, no session and no per-receiver protocol to interact with, so the BLE/Wi-Fi notion of probing what the device trusts above the link does not apply on the RF side. Everything an attacker can influence is already decided at the signal level (Attack): once you control the position and time the receiver derives, you control every downstream system that trusts them, navigation, geofencing, timestamps, a PPS timing reference. The application-layer impact is therefore assessed in the victim system (does a false position/time cause unsafe behaviour?), not by attacking a GNSS protocol that has no interactive surface." } } }; diff --git a/src/data/toolchains/gsm.js b/src/data/toolchains/gsm.js index e1ccd16..2480078 100644 --- a/src/data/toolchains/gsm.js +++ b/src/data/toolchains/gsm.js @@ -1,7 +1,7 @@ export default { "status": "complete", "facts": [ - { "k": "Bands", "v": "GSM-850 / E-GSM-900 / DCS-1800 / PCS-1900 MHz — exact band depends on region (900/1800 in most of the world, 850/1900 in the Americas)" }, + { "k": "Bands", "v": "GSM-850 / E-GSM-900 / DCS-1800 / PCS-1900 MHz, exact band depends on region (900/1800 in most of the world, 850/1900 in the Americas)" }, { "k": "Channels", "v": "200 kHz carriers indexed by ARFCN; each carrier is TDMA-divided into 8 timeslots. Downlink and uplink are paired (FDD), spaced 45 MHz (900) / 95 MHz (1800)" }, { "k": "Modulation", "v": "GMSK (0.3 BT Gaussian-filtered MSK) at 270.833 kbit/s; EDGE adds 8-PSK on top" }, { "k": "Logical channels", "v": "BCCH broadcasts cell info · CCCH (PCH/AGCH/RACH) pages and grants · SDCCH carries signalling (incl. location updates, SMS) · TCH carries voice" }, @@ -13,49 +13,49 @@ export default { "IG": { "note": "Work out the cell and the target before any RF capture. GSM is a network you observe, not a single device: a base station (BTS) broadcasts a cell on a BCCH carrier, identified by its MCC/MNC/LAC/Cell-ID and the operator behind it. Most of what you need is read passively from the cell's own broadcasts, or from public references (operator band plans, cell-tower databases, the SIM's IMSI prefix). The headline weakness to confirm is which A5 cipher the cell runs and whether it ever sends the IMSI in the clear.", "lookFor": [ - "Band in use for the region (850/900/1800/1900) — sets which ARFCN range to scan and which radios reach it (RTL-SDR reaches GSM-900/850 and DCS-1800, but check its 1.766 GHz ceiling against PCS-1900).", - "Cell identity from the BCCH: MCC (country), MNC (operator), LAC (location area) and Cell-ID — cross-reference operator and physical tower in OpenCellID / cell databases.", - "Cipher in force: A5/0 (none), A5/1 (crackable), A5/2 (deprecated) or A5/3 (KASUMI) — readable from the Cipher Mode Command on the air; it decides whether the Break-crypto step is even feasible.", + "Band in use for the region (850/900/1800/1900), sets which ARFCN range to scan and which radios reach it (RTL-SDR reaches GSM-900/850 and DCS-1800, but check its 1.766 GHz ceiling against PCS-1900).", + "Cell identity from the BCCH: MCC (country), MNC (operator), LAC (location area) and Cell-ID, cross-reference operator and physical tower in OpenCellID / cell databases.", + "Cipher in force: A5/0 (none), A5/1 (crackable), A5/2 (deprecated) or A5/3 (KASUMI), readable from the Cipher Mode Command on the air; it decides whether the Break-crypto step is even feasible.", "Identities exposed: does the cell page by IMSI or by TMSI, and does it force an IMSI during location update? Frequent IMSI exposure is both a privacy finding and the signature of an IMSI catcher.", - "Frequency-hopping: is the target channel hopping (a hopping sequence from the BCCH) — which complicates single-channel capture — or static.", + "Frequency-hopping: is the target channel hopping (a hopping sequence from the BCCH), which complicates single-channel capture, or static.", "2G fallback context: is the device 2G-only, or a 4G/5G phone that can be downgraded to GSM? Downgrade is what makes legacy GSM attacks relevant in 2026." ] }, "SP": { - "note": "Find a live cell in the spectrum. A GSM carrier is 200 kHz wide and a downlink BCCH transmits continuously, so it shows up as a steady picket in the waterfall — but the reliable way to find cells is to scan for the FCCH/SCH synchronisation bursts every BTS sends, which also gives you each carrier's ARFCN, its signal strength and your radio's clock error (ppm). RTL-SDR is enough for GSM-900/850 and DCS-1800; PCS-1900 is right at the top of its range, so prefer a HackRF/bladeRF/USRP there.", + "note": "Find a live cell in the spectrum. A GSM carrier is 200 kHz wide and a downlink BCCH transmits continuously, so it shows up as a steady picket in the waterfall, but the reliable way to find cells is to scan for the FCCH/SCH synchronisation bursts every BTS sends, which also gives you each carrier's ARFCN, its signal strength and your radio's clock error (ppm). RTL-SDR is enough for GSM-900/850 and DCS-1800; PCS-1900 is right at the top of its range, so prefer a HackRF/bladeRF/USRP there.", "tools": [ { "tool": "kalibrate-rtl", "role": "ARFCN / cell scanner", "why": "Sweeps a whole GSM band and reports every ARFCN with a live BTS, its power, and the ppm clock offset to feed back into the capture tools. The standard first move: it tells you exactly which channel to camp on.", "caveat": "The -rtl fork is RTL-SDR-specific; use a HackRF/UHD kalibrate fork for those radios.", "deps": ["rtl-sdr-v4", "hackrf-one", "bladerf-2-micro", "usrp-b210"] }, - { "tool": "gqrx", "role": "Spectrum / waterfall view", "why": "Eyeball the band to confirm the 200 kHz GSM pickets and judge signal quality before committing a capture — quick visual sanity check alongside the kalibrate scan.", "deps": ["rtl-sdr-v4", "hackrf-one", "bladerf-2-micro", "usrp-b210"] } + { "tool": "gqrx", "role": "Spectrum / waterfall view", "why": "Eyeball the band to confirm the 200 kHz GSM pickets and judge signal quality before committing a capture, quick visual sanity check alongside the kalibrate scan.", "deps": ["rtl-sdr-v4", "hackrf-one", "bladerf-2-micro", "usrp-b210"] } ] }, "PHY": { - "note": "No standalone GSM demodulator in this kit — the GMSK burst demodulation (PHY) and the burst-to-frame decoding (LL) happen together in gr-gsm on the SDR, so they live at the Capture step. GSM packs 8 users into one 200 kHz carrier by TDMA, so 'capturing a channel' means demodulating the whole carrier and then picking out the timeslot and logical channel (BCCH/CCCH/SDCCH/TCH) you want." + "note": "No standalone GSM demodulator in this kit, the GMSK burst demodulation (PHY) and the burst-to-frame decoding (LL) happen together in gr-gsm on the SDR, so they live at the Capture step. GSM packs 8 users into one 200 kHz carrier by TDMA, so 'capturing a channel' means demodulating the whole carrier and then picking out the timeslot and logical channel (BCCH/CCCH/SDCCH/TCH) you want." }, "LL": { - "note": "Capture and decode the GSM downlink. Tune the ARFCN that kalibrate found, let gr-gsm demodulate the GMSK bursts and decode the control channels, and it forwards each frame as GSMTAP over UDP straight into Wireshark — where you read the System Information, paging, assignment and SDCCH signalling. This is the workhorse path: ARFCN scan → grgsm_livemon → GSMTAP → Wireshark.", + "note": "Capture and decode the GSM downlink. Tune the ARFCN that kalibrate found, let gr-gsm demodulate the GMSK bursts and decode the control channels, and it forwards each frame as GSMTAP over UDP straight into Wireshark, where you read the System Information, paging, assignment and SDCCH signalling. This is the workhorse path: ARFCN scan → grgsm_livemon → GSMTAP → Wireshark.", "decoder": "wireshark", "tools": [ - { "tool": "gr-gsm", "role": "Primary capture / demod", "why": "grgsm_livemon demodulates a found ARFCN and decodes BCCH/CCCH/SDCCH bursts, streaming GSMTAP to Wireshark in real time. The de-facto open-source GSM receiver (the successor to airprobe) — runs on any of the listed SDRs.", "caveat": "Downlink-focused and easiest on a non-hopping channel; following a hopping TCH or the uplink is materially harder.", "deps": ["rtl-sdr-v4", "hackrf-one", "bladerf-2-micro", "usrp-b210"] }, - { "tool": "imsi-catcher", "role": "Passive IMSI / TMSI extractor", "why": "Reads gr-gsm's GSMTAP stream and prints the IMSI/TMSI of phones the cell pages — a passive IMSI catcher that harvests identities off the air with no transmit, and the concrete demonstration of GSM's on-air identity exposure.", "deps": ["gr-gsm"], "needs": "A live grgsm_livemon feeding GSMTAP on localhost (it consumes gr-gsm's output, not the radio directly) — so it bonds to gr-gsm at the Capture step." } + { "tool": "gr-gsm", "role": "Primary capture / demod", "why": "grgsm_livemon demodulates a found ARFCN and decodes BCCH/CCCH/SDCCH bursts, streaming GSMTAP to Wireshark in real time. The de-facto open-source GSM receiver (the successor to airprobe), runs on any of the listed SDRs.", "caveat": "Downlink-focused and easiest on a non-hopping channel; following a hopping TCH or the uplink is materially harder.", "deps": ["rtl-sdr-v4", "hackrf-one", "bladerf-2-micro", "usrp-b210"] }, + { "tool": "imsi-catcher", "role": "Passive IMSI / TMSI extractor", "why": "Reads gr-gsm's GSMTAP stream and prints the IMSI/TMSI of phones the cell pages, a passive IMSI catcher that harvests identities off the air with no transmit, and the concrete demonstration of GSM's on-air identity exposure.", "deps": ["gr-gsm"], "needs": "A live grgsm_livemon feeding GSMTAP on localhost (it consumes gr-gsm's output, not the radio directly), so it bonds to gr-gsm at the Capture step." } ] }, "CR": { - "note": "Assess the cipher and, where it is the broken A5/1, recover the session key from the capture. GSM's A5/1 stream cipher has a public attack: precomputed rainbow tables (the Berlin A5/1 Security Project) recover the 64-bit session key Kc from a slice of known keystream, after which the rest of the captured call/SMS decrypts. This is real but heavy — it needs ~1.6–2 TB of tables, a known-plaintext keystream segment from the capture, and the target cell must actually run A5/1. A5/3 (KASUMI) is not broken this way. Recovering keys from live traffic you are not authorised to intercept is illegal in most jurisdictions — treat this as a lab/authorised-test technique.", + "note": "Assess the cipher and, where it is the broken A5/1, recover the session key from the capture. GSM's A5/1 stream cipher has a public attack: precomputed rainbow tables (the Berlin A5/1 Security Project) recover the 64-bit session key Kc from a slice of known keystream, after which the rest of the captured call/SMS decrypts. This is real but heavy, it needs ~1.6 to 2 TB of tables, a known-plaintext keystream segment from the capture, and the target cell must actually run A5/1. A5/3 (KASUMI) is not broken this way. Recovering keys from live traffic you are not authorised to intercept is illegal in most jurisdictions, treat this as a lab/authorised-test technique.", "tools": [ { "tool": "kraken-a51", "role": "A5/1 key recovery", "why": "Recovers the A5/1 session key Kc from a captured keystream segment using the rainbow tables; with Kc the captured A5/1 session decrypts. The reference open A5/1 cracker.", "caveat": "Needs the ~2 TB rainbow tables and a clean known-keystream slice; no effect on A5/3/A5/4 (KASUMI). Use only on traffic you are authorised to decrypt.", "deps": ["wireshark"], "needs": "An A5/1-encrypted capture with a recoverable known-keystream segment: capture the cell at the Capture step (gr-gsm → GSMTAP → Wireshark), isolate the burst/keystream, then feed it to Kraken alongside the rainbow tables." } ] }, "AT": { - "note": "Actively impersonate the network — AUTHORISED testing only (a licensed lab / shielded enclosure with explicit permission); transmitting a GSM cell on-air is illegal otherwise. Because a GSM phone authenticates the network one-way only (the cell never proves itself), a rogue BTS — the classic IMSI catcher — can impersonate a real cell: stand up your own BCCH with the target's MCC/MNC/LAC at a higher level so handsets reselect and attach, issue an Identity Request to harvest the IMSI/IMEI, set A5/0 (no ciphering) or downgrade to A5/1, and from there page, locate or intercept. Stand the cell up with the Osmocom stack (osmo-trx + osmo-bts + osmo-bsc + osmo-msc + osmo-hlr) or the all-in-one OpenBTS, on a clock-disciplined TX-capable SDR. (The lighter-footprint, no-transmit alternative is the passive IMSI catch at the Capture step — Oros42's tool reading IMSIs straight off the broadcast.)", + "note": "Actively impersonate the network, AUTHORISED testing only (a licensed lab / shielded enclosure with explicit permission); transmitting a GSM cell on-air is illegal otherwise. Because a GSM phone authenticates the network one-way only (the cell never proves itself), a rogue BTS, the classic IMSI catcher, can impersonate a real cell: stand up your own BCCH with the target's MCC/MNC/LAC at a higher level so handsets reselect and attach, issue an Identity Request to harvest the IMSI/IMEI, set A5/0 (no ciphering) or downgrade to A5/1, and from there page, locate or intercept. Stand the cell up with the Osmocom stack (osmo-trx + osmo-bts + osmo-bsc + osmo-msc + osmo-hlr) or the all-in-one OpenBTS, on a clock-disciplined TX-capable SDR. (The lighter-footprint, no-transmit alternative is the passive IMSI catch at the Capture step, Oros42's tool reading IMSIs straight off the broadcast.)", "tools": [ - { "tool": "osmo-bts", "role": "Rogue BTS / active IMSI catcher", "why": "The Osmocom GSM stack stands up your own 2G cell on an SDR — osmo-trx drives the radio, osmo-bts is the base station, osmo-bsc/osmo-msc/osmo-hlr the core — broadcasting your own BCCH above the real cell so handsets reselect and attach. With one-way GSM auth the fake cell issues an Identity Request to harvest the IMSI/IMEI, forces A5/0, and downgrades or intercepts. The reference open rogue-cell / IMSI-catcher platform.", "deps": ["usrp-b210", "bladerf-2-micro"], "needs": "A clock-disciplined TX-capable SDR (USRP B210 via osmo-trx-uhd, or a bladeRF) and the full Osmocom stack (osmo-trx + osmo-bts + osmo-bsc + osmo-msc + osmo-hlr) plus test SIMs. AUTHORISED, RF-shielded lab use only.", "caveat": "Transmits a live GSM cell in licensed spectrum — authorised, shielded testing only." }, - { "tool": "openbts", "role": "Rogue BTS (all-in-one)", "why": "OpenBTS replaces the GSM RAN+core with a single application on a USRP, presenting a GSM air interface and routing calls/SMS over SIP/Asterisk so a handset attaches to your cell — the original 'GSM in a box' and a more self-contained alternative to the Osmocom stack for fake-BTS / IMSI-catcher work.", "deps": ["usrp-b210", "bladerf-2-micro"], "needs": "A USRP (the classic OpenBTS radio) or compatible SDR and test SIMs; build via the RangeNetworks 'dev' environment. Authorised, RF-shielded lab use only.", "caveat": "Older codebase; transmits a live GSM cell — authorised, shielded use only." } + { "tool": "osmo-bts", "role": "Rogue BTS / active IMSI catcher", "why": "The Osmocom GSM stack stands up your own 2G cell on an SDR, osmo-trx drives the radio, osmo-bts is the base station, osmo-bsc/osmo-msc/osmo-hlr the core, broadcasting your own BCCH above the real cell so handsets reselect and attach. With one-way GSM auth the fake cell issues an Identity Request to harvest the IMSI/IMEI, forces A5/0, and downgrades or intercepts. The reference open rogue-cell / IMSI-catcher platform.", "deps": ["usrp-b210", "bladerf-2-micro"], "needs": "A clock-disciplined TX-capable SDR (USRP B210 via osmo-trx-uhd, or a bladeRF) and the full Osmocom stack (osmo-trx + osmo-bts + osmo-bsc + osmo-msc + osmo-hlr) plus test SIMs. AUTHORISED, RF-shielded lab use only.", "caveat": "Transmits a live GSM cell in licensed spectrum, authorised, shielded testing only." }, + { "tool": "openbts", "role": "Rogue BTS (all-in-one)", "why": "OpenBTS replaces the GSM RAN+core with a single application on a USRP, presenting a GSM air interface and routing calls/SMS over SIP/Asterisk so a handset attaches to your cell, the original 'GSM in a box' and a more self-contained alternative to the Osmocom stack for fake-BTS / IMSI-catcher work.", "deps": ["usrp-b210", "bladerf-2-micro"], "needs": "A USRP (the classic OpenBTS radio) or compatible SDR and test SIMs; build via the RangeNetworks 'dev' environment. Authorised, RF-shielded lab use only.", "caveat": "Older codebase; transmits a live GSM cell, authorised, shielded use only." } ] }, "AP": { - "note": "Above the link, GSM's 'app layer' is its signalling and bearer services rather than IP. Once SDCCH/TCH frames are decoded (and decrypted, where A5/1 was broken), the payloads to inspect are the L3 mobility/call-control messages and SMS — including silent/Class-0 pings used to locate a handset. There is no dedicated app-layer tool in this kit beyond the dissector: read the decoded GSM L3 and SMS layers directly in Wireshark on the GSMTAP capture from the Capture step.", + "note": "Above the link, GSM's 'app layer' is its signalling and bearer services rather than IP. Once SDCCH/TCH frames are decoded (and decrypted, where A5/1 was broken), the payloads to inspect are the L3 mobility/call-control messages and SMS, including silent/Class-0 pings used to locate a handset. There is no dedicated app-layer tool in this kit beyond the dissector: read the decoded GSM L3 and SMS layers directly in Wireshark on the GSMTAP capture from the Capture step.", "tools": [ - { "tool": "wireshark", "role": "L3 / SMS inspection", "why": "Dissects the decoded GSM signalling stack — Mobility Management, Call Control and SMS — straight from the GSMTAP capture, so you can read paging, location updates and SMS payloads without extra tooling.", "deps": ["gr-gsm"], "needs": "The GSMTAP capture produced at the Capture step (gr-gsm → Wireshark); inspect the GSM L3/SMS layers in the same Wireshark session." } + { "tool": "wireshark", "role": "L3 / SMS inspection", "why": "Dissects the decoded GSM signalling stack, Mobility Management, Call Control and SMS, straight from the GSMTAP capture, so you can read paging, location updates and SMS payloads without extra tooling.", "deps": ["gr-gsm"], "needs": "The GSMTAP capture produced at the Capture step (gr-gsm → Wireshark); inspect the GSM L3/SMS layers in the same Wireshark session." } ] } } diff --git a/src/data/toolchains/lora.js b/src/data/toolchains/lora.js index 50ebc9d..525f950 100644 --- a/src/data/toolchains/lora.js +++ b/src/data/toolchains/lora.js @@ -1,66 +1,66 @@ export default { "status": "complete", "facts": [ - { "k": "Band", "v": "Sub-GHz ISM, regional: EU868 (863–870 MHz) · US915 (902–928 MHz) · AS923 (sub-banded family, ~915–928 MHz) · EU433 (433.05–434.79 MHz) · also AU915 / CN470 / IN865 / KR920" }, - { "k": "Modulation", "v": "CSS (Chirp Spread Spectrum) — a chirp sweeps the band; data is encoded in the chirp’s cyclic start offset. Spreading factor SF7–SF12 trades data rate for range/sensitivity (higher SF = slower, longer reach)." }, - { "k": "Bandwidth", "v": "125 / 250 / 500 kHz in LoRaWAN regional plans (SX127x/SX126x chips also support 7.8–62.5 kHz, but those are not used by LoRaWAN)." }, + { "k": "Band", "v": "Sub-GHz ISM, regional: EU868 (863 to 870 MHz) · US915 (902 to 928 MHz) · AS923 (sub-banded family, ~915 to 928 MHz) · EU433 (433.05 to 434.79 MHz) · also AU915 / CN470 / IN865 / KR920" }, + { "k": "Modulation", "v": "CSS (Chirp Spread Spectrum), a chirp sweeps the band; data is encoded in the chirp’s cyclic start offset. Spreading factor SF7 to SF12 trades data rate for range/sensitivity (higher SF = slower, longer reach)." }, + { "k": "Bandwidth", "v": "125 / 250 / 500 kHz in LoRaWAN regional plans (SX127x/SX126x chips also support 7.8 to 62.5 kHz, but those are not used by LoRaWAN)." }, { "k": "LoRaWAN MAC", "v": "PHYPayload = MHDR | MACPayload | MIC(4B). MHDR carries MType. MACPayload = FHDR(DevAddr, FCtrl, FCnt, FOpts) | FPort | FRMPayload. MIC is AES-128-CMAC (RFC 4493)." }, { "k": "Crypto", "v": "FRMPayload encrypted with AES-128 (AppSKey); MIC keyed by NwkSKey. Root keys: AppKey (1.0.x) / NwkKey+AppKey (1.1). Two activation modes: OTAA (keys derived at join) and ABP (static session keys burned in)." }, - { "k": "Join (OTAA)", "v": "JoinRequest = JoinEUI/AppEUI | DevEUI | DevNonce — sent in clear, protected only by a MIC (the key is never transmitted). JoinAccept is encrypted. 1.0.x DevNonce is random (replay risk); 1.1 makes it a monotonic counter and adds a Join Server + split keys." } + { "k": "Join (OTAA)", "v": "JoinRequest = JoinEUI/AppEUI | DevEUI | DevNonce, sent in clear, protected only by a MIC (the key is never transmitted). JoinAccept is encrypted. 1.0.x DevNonce is random (replay risk); 1.1 makes it a monotonic counter and adds a Join Server + split keys." } ], "reference": null, "layers": { "IG": { - "note": "Work out what the device and its network look like before any RF work — no capture yet. LoRa is two layers: the LoRa radio (the CSS chirp) and LoRaWAN (the MAC/network on top). You want to know the region/band it uses (this sets the frequencies you survey), which LoRaWAN version and activation mode it runs, and where the cryptographic weak points are. Much of this comes from the device label/FCC ID, the vendor datasheet, and the network server’s device profile if you have access to it.", + "note": "Work out what the device and its network look like before any RF work, no capture yet. LoRa is two layers: the LoRa radio (the CSS chirp) and LoRaWAN (the MAC/network on top). You want to know the region/band it uses (this sets the frequencies you survey), which LoRaWAN version and activation mode it runs, and where the cryptographic weak points are. Much of this comes from the device label/FCC ID, the vendor datasheet, and the network server’s device profile if you have access to it.", "lookFor": [ - "Radio chipset (Semtech SX127x / SX126x / SX130x gateway) and module vendor (FCC ID, teardown) — sets the supported bands, spreading factors and bandwidths.", + "Radio chipset (Semtech SX127x / SX126x / SX130x gateway) and module vendor (FCC ID, teardown), sets the supported bands, spreading factors and bandwidths.", "Regional band (EU868 / US915 / AS923 / EU433 …): determines the exact frequencies and channel plan to survey, and the SF/BW data-rate set in play.", - "LoRaWAN version: 1.0.x vs 1.1 — 1.1 adds a Join Server, split keys and a monotonic DevNonce; 1.0.x is more exposed to join replay and key-management mistakes.", - "Activation mode: OTAA (session keys derived at each join) vs ABP (static session keys + DevAddr burned into the device — no rotation, frame-counter reset risk).", + "LoRaWAN version: 1.0.x vs 1.1, 1.1 adds a Join Server, split keys and a monotonic DevNonce; 1.0.x is more exposed to join replay and key-management mistakes.", + "Activation mode: OTAA (session keys derived at each join) vs ABP (static session keys + DevAddr burned into the device, no rotation, frame-counter reset risk).", "Key management: is the AppKey a per-device random value, or a default / shared / vendor-wide key? A weak or reused AppKey collapses the whole crypto chain.", - "Identifiers visible on the air: DevAddr (data frames) and DevEUI / JoinEUI(AppEUI) / DevNonce (join requests, in clear) — useful for tracking and for targeting a capture." + "Identifiers visible on the air: DevAddr (data frames) and DevEUI / JoinEUI(AppEUI) / DevNonce (join requests, in clear), useful for tracking and for targeting a capture." ] }, "SP": { - "note": "Find where the device transmits and confirm its channel plan. LoRa lives in narrow sub-GHz ISM bands, so an RTL-SDR is enough to watch a band (unlike 2.4 GHz work) — point it at the regional sub-band and look for the unmistakable diagonal chirp sweeps of CSS on the waterfall. Devices are duty-cycle limited and often transmit infrequently, so a survey may mean watching for a while; a real LoRaWAN gateway can log every channel at once if you have one.", + "note": "Find where the device transmits and confirm its channel plan. LoRa lives in narrow sub-GHz ISM bands, so an RTL-SDR is enough to watch a band (unlike 2.4 GHz work), point it at the regional sub-band and look for the unmistakable diagonal chirp sweeps of CSS on the waterfall. Devices are duty-cycle limited and often transmit infrequently, so a survey may mean watching for a while; a real LoRaWAN gateway can log every channel at once if you have one.", "tools": [ - { "tool": "gqrx", "role": "Spectrum / waterfall view", "why": "See the live sub-GHz spectrum and spot the diagonal CSS chirps — confirm the band, channels and roughly how busy the network is. Cheap and quick on an RTL-SDR since LoRa sits well below 1.7 GHz.", "deps": ["rtl-sdr-v4", "hackrf-one"] }, - { "tool": "chirpcat", "role": "Gateway-fed discovery & classification", "why": "Electronic Cats’ LoRa/LoRaWAN platform running on a RAK WisGate Connect gateway: as it ingests every channel it clusters packets by RF characteristics and scores/classifies targets, giving a live picture of the LoRaWAN devices on the air before you commit to a target.", "caveat": "Needs a multi-channel gateway feed (the RAK WisGate Connect / SX1302); new project — verify maturity before relying on it.", "deps": ["rak-wisgate-connect"] }, - { "tool": "catnip", "role": "SX1262 spectrum analyzer", "why": "catnip turns the CatSniffer's SX1262 into a real-time spectrum analyzer over the LoRa sub-bands — watch the channels and CSS chirp activity from the board itself, a no-SDR complement to the gqrx waterfall.", "deps": ["catsniffer"] } + { "tool": "gqrx", "role": "Spectrum / waterfall view", "why": "See the live sub-GHz spectrum and spot the diagonal CSS chirps, confirm the band, channels and roughly how busy the network is. Cheap and quick on an RTL-SDR since LoRa sits well below 1.7 GHz.", "deps": ["rtl-sdr-v4", "hackrf-one"] }, + { "tool": "chirpcat", "role": "Gateway-fed discovery & classification", "why": "Electronic Cats’ LoRa/LoRaWAN platform running on a RAK WisGate Connect gateway: as it ingests every channel it clusters packets by RF characteristics and scores/classifies targets, giving a live picture of the LoRaWAN devices on the air before you commit to a target.", "caveat": "Needs a multi-channel gateway feed (the RAK WisGate Connect / SX1302); new project, verify maturity before relying on it.", "deps": ["rak-wisgate-connect"] }, + { "tool": "catnip", "role": "SX1262 spectrum analyzer", "why": "catnip turns the CatSniffer's SX1262 into a real-time spectrum analyzer over the LoRa sub-bands, watch the channels and CSS chirp activity from the board itself, a no-SDR complement to the gqrx waterfall.", "deps": ["catsniffer"] } ] }, "PHY": { - "note": "No off-the-shelf hardware demodulator for LoRa CSS in this kit — you de-chirp it in software on an SDR. The receiver multiplies the incoming chirp by a reference down-chirp and takes an FFT, turning each symbol into a frequency bin it can read; doing this reliably (with timing and frequency-offset correction, at low SNR) is exactly what gr-lora_sdr implements. Because demodulating and framing happen together in the same software flow, the actual capture tools live at the next step." + "note": "No off-the-shelf hardware demodulator for LoRa CSS in this kit, you de-chirp it in software on an SDR. The receiver multiplies the incoming chirp by a reference down-chirp and takes an FFT, turning each symbol into a frequency bin it can read; doing this reliably (with timing and frequency-offset correction, at low SNR) is exactly what gr-lora_sdr implements. Because demodulating and framing happen together in the same software flow, the actual capture tools live at the next step." }, "LL": { - "note": "Capture the chirps and turn them into LoRaWAN frames. Two paths: de-chirp the CSS waveform off an SDR in software (gr-lora_sdr / lorattack), or — if you have gateway access — read whole LoRaWAN frames straight off a real concentrator, which captures every channel at once and sees both uplink and downlink. Either way you recover the PHYPayload and parse the LoRaWAN MAC: MHDR/MType, the FHDR with DevAddr, frame counter and options, and — for OTAA joins — the JoinEUI/DevEUI/DevNonce, which travel in clear. The application payload stays AES-128 encrypted until you have the keys. Export to a LoRaTap-tagged PCAP and dissect it in Wireshark.", + "note": "Capture the chirps and turn them into LoRaWAN frames. Two paths: de-chirp the CSS waveform off an SDR in software (gr-lora_sdr / lorattack), or, if you have gateway access, read whole LoRaWAN frames straight off a real concentrator, which captures every channel at once and sees both uplink and downlink. Either way you recover the PHYPayload and parse the LoRaWAN MAC: MHDR/MType, the FHDR with DevAddr, frame counter and options, and, for OTAA joins, the JoinEUI/DevEUI/DevNonce, which travel in clear. The application payload stays AES-128 encrypted until you have the keys. Export to a LoRaTap-tagged PCAP and dissect it in Wireshark.", "decoder": "wireshark", "tools": [ - { "tool": "gr-lora_sdr", "role": "Primary CSS demodulator", "why": "EPFL’s full GNU Radio LoRa transceiver: a complete CSS receiver with sync, timing and frequency-offset correction that decodes down to very low SNR — the reference open-source way to get LoRa frames off an SDR. Pick the radio by the band/bandwidth you need.", "caveat": "GNU Radio flowgraph setup; sample-rate must cover the 125/250/500 kHz bandwidth.", "deps": ["hackrf-one", "usrp-b210", "bladerf-2-micro", "rtl-sdr-v4"] }, - { "tool": "lorattack", "role": "LoRaWAN multi-channel sniffer", "why": "Purpose-built LoRaWAN assessment toolkit: multi-channel SDR sniffing with session-based capture, automatic handshake storage, and Wireshark-compatible PCAP output (LoRaTap DLT) — captures and organises the join/data frames you’ll crack and replay later.", "caveat": "Actively under construction; sniffer tested mainly at 125 kHz; USRP-oriented.", "deps": ["usrp-b210"] }, - { "tool": "chirpcat", "role": "Gateway frame capture (uplink + downlink)", "why": "With gateway access, ChirpCat reads whole LoRaWAN frames — both uplink and downlink — straight off a RAK WisGate Connect via the Semtech UDP packet forwarder, so you capture the full bidirectional exchange across every channel at once without an SDR de-chirp flow, and dispatch follow/capture tasks to CatSniffer workers.", "caveat": "Requires the RAK WisGate Connect gateway (or another SX130x concentrator running the Semtech packet forwarder); new project.", "deps": ["rak-wisgate-connect"] }, - { "tool": "whad", "role": "LoRaWAN sniff (STM32WL)", "why": "WHAD's LoRaWAN domain runs on an STM32WLxx board (its stm32wlxx-firmware), pulling LoRa/LoRaWAN frames into PCAP/Scapy from the same framework used across BLE and 802.15.4 — a single-board capture path when you have an STM32WL radio rather than an SDR.", "caveat": "WHAD's LoRaWAN support is newer than its BLE/802.15.4 domains — verify coverage for your region and spreading factor.", "deps": ["stm32wlxx"] }, - { "tool": "catnip", "role": "LoRa / Meshtastic capture & decode", "why": "catnip captures LoRa frames off the CatSniffer's SX1262 into Wireshark over an extcap, and its Meshtastic suite decodes Meshtastic packets live or offline — trying the default/known channel PSKs to decrypt, with a TUI chat dashboard. The CatSniffer-native path to LoRa and Meshtastic traffic without an SDR de-chirp flow.", "deps": ["catsniffer"], "caveat": "Single-radio LoRa — set the region/SF/BW; Meshtastic decryption depends on holding the channel PSK (the defaults are tried automatically)." }, - { "tool": "lora-wideband-decoder", "role": "Wideband multi-protocol intercept", "why": "Instead of de-chirping one channel, it streams wideband IQ off a fast SDR and decodes the WHOLE LoRa sub-band at once — Meshtastic, LoRaWAN and MeshCore across SF7–SF12 at every bandwidth — in software, near-real-time, surfacing packets, node identities and a live waterfall in a local web UI. The widest-coverage capture when you don't yet know the exact channel or spreading factor.", "deps": ["bladerf-2-micro", "usrp-b210"], "caveat": "Wants a wideband SDR and a multi-core host (validated ~28 Msps on bladeRF native / USRP B210; a HackRF is too narrow); decodes in its own Flask web UI rather than Wireshark. Intercept receiver — authorised use only." } + { "tool": "gr-lora_sdr", "role": "Primary CSS demodulator", "why": "EPFL’s full GNU Radio LoRa transceiver: a complete CSS receiver with sync, timing and frequency-offset correction that decodes down to very low SNR, the reference open-source way to get LoRa frames off an SDR. Pick the radio by the band/bandwidth you need.", "caveat": "GNU Radio flowgraph setup; sample-rate must cover the 125/250/500 kHz bandwidth.", "deps": ["hackrf-one", "usrp-b210", "bladerf-2-micro", "rtl-sdr-v4"] }, + { "tool": "lorattack", "role": "LoRaWAN multi-channel sniffer", "why": "Purpose-built LoRaWAN assessment toolkit: multi-channel SDR sniffing with session-based capture, automatic handshake storage, and Wireshark-compatible PCAP output (LoRaTap DLT), captures and organises the join/data frames you’ll crack and replay later.", "caveat": "Actively under construction; sniffer tested mainly at 125 kHz; USRP-oriented.", "deps": ["usrp-b210"] }, + { "tool": "chirpcat", "role": "Gateway frame capture (uplink + downlink)", "why": "With gateway access, ChirpCat reads whole LoRaWAN frames, both uplink and downlink, straight off a RAK WisGate Connect via the Semtech UDP packet forwarder, so you capture the full bidirectional exchange across every channel at once without an SDR de-chirp flow, and dispatch follow/capture tasks to CatSniffer workers.", "caveat": "Requires the RAK WisGate Connect gateway (or another SX130x concentrator running the Semtech packet forwarder); new project.", "deps": ["rak-wisgate-connect"] }, + { "tool": "whad", "role": "LoRaWAN sniff (STM32WL)", "why": "WHAD's LoRaWAN domain runs on an STM32WLxx board (its stm32wlxx-firmware), pulling LoRa/LoRaWAN frames into PCAP/Scapy from the same framework used across BLE and 802.15.4, a single-board capture path when you have an STM32WL radio rather than an SDR.", "caveat": "WHAD's LoRaWAN support is newer than its BLE/802.15.4 domains, verify coverage for your region and spreading factor.", "deps": ["stm32wlxx"] }, + { "tool": "catnip", "role": "LoRa / Meshtastic capture & decode", "why": "catnip captures LoRa frames off the CatSniffer's SX1262 into Wireshark over an extcap, and its Meshtastic suite decodes Meshtastic packets live or offline, trying the default/known channel PSKs to decrypt, with a TUI chat dashboard. The CatSniffer-native path to LoRa and Meshtastic traffic without an SDR de-chirp flow.", "deps": ["catsniffer"], "caveat": "Single-radio LoRa, set the region/SF/BW; Meshtastic decryption depends on holding the channel PSK (the defaults are tried automatically)." }, + { "tool": "lora-wideband-decoder", "role": "Wideband multi-protocol intercept", "why": "Instead of de-chirping one channel, it streams wideband IQ off a fast SDR and decodes the WHOLE LoRa sub-band at once, Meshtastic, LoRaWAN and MeshCore across SF7 to SF12 at every bandwidth, in software, near-real-time, surfacing packets, node identities and a live waterfall in a local web UI. The widest-coverage capture when you don't yet know the exact channel or spreading factor.", "deps": ["bladerf-2-micro", "usrp-b210"], "caveat": "Wants a wideband SDR and a multi-core host (validated ~28 Msps on bladeRF native / USRP B210; a HackRF is too narrow); decodes in its own Flask web UI rather than Wireshark. Intercept receiver, authorised use only." } ] }, "CR": { - "note": "Assess the LoRaWAN crypto. There is no feasible brute force of a random AES-128 AppKey — the weaknesses are in how keys and nonces are managed, and each assessment consumes a capture from the previous step. Check for: a default / shared / vendor-wide AppKey (if you can guess or recover it, you derive the session keys and decrypt everything); ABP devices with static, never-rotated session keys and a frame counter that resets on reboot; and on LoRaWAN 1.0.x, DevNonce reuse enabling join replay (1.1 closes this with a monotonic DevNonce, a Join Server and split keys). Where the AppKey is known or weak, derive the session keys and validate against the captured MIC.", + "note": "Assess the LoRaWAN crypto. There is no feasible brute force of a random AES-128 AppKey, the weaknesses are in how keys and nonces are managed, and each assessment consumes a capture from the previous step. Check for: a default / shared / vendor-wide AppKey (if you can guess or recover it, you derive the session keys and decrypt everything); ABP devices with static, never-rotated session keys and a frame counter that resets on reboot; and on LoRaWAN 1.0.x, DevNonce reuse enabling join replay (1.1 closes this with a monotonic DevNonce, a Join Server and split keys). Where the AppKey is known or weak, derive the session keys and validate against the captured MIC.", "tools": [ - { "tool": "loracrack", "role": "Weak/shared AppKey exploit", "why": "PoC that, given a known, default or guessable AppKey, derives the session keys from captured join + data frames and validates via the MIC — demonstrates how a single reused AppKey across a fleet collapses confidentiality.", "deps": ["wireshark"], "needs": "A capture containing the OTAA join (and following data frames) from the Capture step, exported as PCAP from Wireshark, plus a candidate AppKey (default/leaked/guessed).", "caveat": "Exploits weak/reused keys; it does NOT brute-force a strong random AES-128 AppKey." }, - { "tool": "laf", "role": "Parse / analyse / crack", "why": "IOActive’s LoRaWAN auditing toolkit: craft, parse, analyse and crack LoRaWAN packets — recompute and check MICs, test key candidates, and pull apart the frames you captured to find management mistakes.", "deps": ["wireshark"], "needs": "Captured LoRaWAN frames (join + uplink/downlink) from the Capture step as PCAP." } + { "tool": "loracrack", "role": "Weak/shared AppKey exploit", "why": "PoC that, given a known, default or guessable AppKey, derives the session keys from captured join + data frames and validates via the MIC, demonstrates how a single reused AppKey across a fleet collapses confidentiality.", "deps": ["wireshark"], "needs": "A capture containing the OTAA join (and following data frames) from the Capture step, exported as PCAP from Wireshark, plus a candidate AppKey (default/leaked/guessed).", "caveat": "Exploits weak/reused keys; it does NOT brute-force a strong random AES-128 AppKey." }, + { "tool": "laf", "role": "Parse / analyse / crack", "why": "IOActive’s LoRaWAN auditing toolkit: craft, parse, analyse and crack LoRaWAN packets, recompute and check MICs, test key candidates, and pull apart the frames you captured to find management mistakes.", "deps": ["wireshark"], "needs": "Captured LoRaWAN frames (join + uplink/downlink) from the Capture step as PCAP." } ] }, "AT": { - "note": "Actively probe or take over, once you can read the frames. The classic LoRaWAN attacks are replay and forging: replay a captured uplink/join (especially against 1.0.x DevNonce or an ABP device whose frame counter resets) to cause acceptance, desynchronisation or denial of service; or, with recovered session keys, craft and inject valid frames. You can also fuzz the network server by transmitting malformed frames at it. These need transmit-capable hardware, not just an RX dongle — a CatSniffer can transmit on Sub-GHz/LoRa, and standing up a ChirpStack network server gives you a server side to replay or fuzz against and watch.", + "note": "Actively probe or take over, once you can read the frames. The classic LoRaWAN attacks are replay and forging: replay a captured uplink/join (especially against 1.0.x DevNonce or an ABP device whose frame counter resets) to cause acceptance, desynchronisation or denial of service; or, with recovered session keys, craft and inject valid frames. You can also fuzz the network server by transmitting malformed frames at it. These need transmit-capable hardware, not just an RX dongle, a CatSniffer can transmit on Sub-GHz/LoRa, and standing up a ChirpStack network server gives you a server side to replay or fuzz against and watch.", "tools": [ - { "tool": "lorattack", "role": "Replay & crafted-frame attacks", "why": "Beyond sniffing, it replays specific payloads to probe known LoRaWAN weaknesses and crafts packets for a session — the practical path to test replay/desync against a target from one toolkit.", "caveat": "Transmission features need more testing per the author; transmits — only against networks you are authorised to test.", "deps": ["usrp-b210"] }, - { "tool": "catsniffer", "role": "LoRa replay & transmit fuzzing", "why": "Because the CatSniffer’s CC1352 can transmit on Sub-GHz/LoRa, it can re-send captured frames to test replay (e.g. against a ChirpStack network server) and transmit malformed/mutated frames to fuzz how the server and devices handle them — an inexpensive transmit-capable LoRa attacker.", "caveat": "Single-channel LoRa transmit (not multi-channel); transmits — only against networks you are authorised to test.", "deps": ["chirpstack"], "needs": "Captured uplink/join frames from the Capture step to replay, and a target network server (e.g. a ChirpStack instance) to replay or fuzz against." }, + { "tool": "lorattack", "role": "Replay & crafted-frame attacks", "why": "Beyond sniffing, it replays specific payloads to probe known LoRaWAN weaknesses and crafts packets for a session, the practical path to test replay/desync against a target from one toolkit.", "caveat": "Transmission features need more testing per the author; transmits, only against networks you are authorised to test.", "deps": ["usrp-b210"] }, + { "tool": "catsniffer", "role": "LoRa replay & transmit fuzzing", "why": "Because the CatSniffer’s CC1352 can transmit on Sub-GHz/LoRa, it can re-send captured frames to test replay (e.g. against a ChirpStack network server) and transmit malformed/mutated frames to fuzz how the server and devices handle them, an inexpensive transmit-capable LoRa attacker.", "caveat": "Single-channel LoRa transmit (not multi-channel); transmits, only against networks you are authorised to test.", "deps": ["chirpstack"], "needs": "Captured uplink/join frames from the Capture step to replay, and a target network server (e.g. a ChirpStack instance) to replay or fuzz against." }, { "tool": "laf", "role": "Forge & send", "why": "Crafts and sends LoRaWAN packets (with valid MICs once keys are known) to test how the network server handles forged, replayed or malformed frames.", "deps": ["hackrf-one", "usrp-b210", "bladerf-2-micro"], "needs": "A transmit-capable SDR and, for valid-MIC frames, session keys recovered at the Break-the-crypto step." } ] }, "AP": { - "note": "Above the LoRaWAN MAC there is little universal protocol to attack — the application payload is just AES-128-encrypted bytes whose meaning is device-specific (a sensor reading, a command), and once you hold the AppSKey you decrypt and inspect it with the same tools that broke the crypto. The richer application surface is the network/application server itself (its API, integrations and downlink handling); standing up an open-source LoRaWAN server such as ChirpStack is the usual way to model that server side, but assessing a specific deployment’s app server is out of band for this RF toolchain." + "note": "Above the LoRaWAN MAC there is little universal protocol to attack, the application payload is just AES-128-encrypted bytes whose meaning is device-specific (a sensor reading, a command), and once you hold the AppSKey you decrypt and inspect it with the same tools that broke the crypto. The richer application surface is the network/application server itself (its API, integrations and downlink handling); standing up an open-source LoRaWAN server such as ChirpStack is the usual way to model that server side, but assessing a specific deployment’s app server is out of band for this RF toolchain." } } }; diff --git a/src/data/toolchains/lte.js b/src/data/toolchains/lte.js index d414e8c..c9ed70f 100644 --- a/src/data/toolchains/lte.js +++ b/src/data/toolchains/lte.js @@ -1,67 +1,67 @@ export default { "status": "complete", "facts": [ - { "k": "Band", "v": "Licensed cellular — common bands ~700 MHz to 2.6 GHz (full E-UTRA set ~450 MHz–3.8 GHz); FDD and TDD duplexing" }, + { "k": "Band", "v": "Licensed cellular, common bands ~700 MHz to 2.6 GHz (full E-UTRA set ~450 MHz to 3.8 GHz); FDD and TDD duplexing" }, { "k": "Bandwidth", "v": "Six channel widths: 1.4, 3, 5, 10, 15, 20 MHz; a carrier is identified by its EARFCN" }, { "k": "Modulation", "v": "Downlink OFDMA, uplink SC-FDMA (DFT-spread OFDM); QPSK/16/64/256-QAM. Frame = 10 ms → 10 subframes (1 ms) → 2 slots (0.5 ms)" }, - { "k": "Cell ID", "v": "PSS gives N_ID(2) (0–2), SSS gives N_ID(1) (0–167); PCI = 3·N_ID(1) + N_ID(2) → 504 physical cell IDs (0–503)" }, + { "k": "Cell ID", "v": "PSS gives N_ID(2) (0 to 2), SSS gives N_ID(1) (0 to 167); PCI = 3·N_ID(1) + N_ID(2) → 504 physical cell IDs (0 to 503)" }, { "k": "Broadcast", "v": "MIB on PBCH (bandwidth, PHICH, SFN); SIB1 on PDSCH via SI-RNTI carries PLMN, cell ID, TAC. SIBs are broadcast in the clear" }, { "k": "Control", "v": "PDCCH carries DCI, addressed by RNTIs (C-RNTI, SI-RNTI, P-RNTI for paging, RA-RNTI); blind-decoding the common search space passively exposes scheduling/identity activity" }, - { "k": "Security", "v": "Air crypto SNOW 3G / AES / ZUC keyed from the USIM’s operator secret (EPS-AKA) — not recoverable from a passive capture. User-plane encryption is optional per bearer; broadcast/paging are unprotected" } + { "k": "Security", "v": "Air crypto SNOW 3G / AES / ZUC keyed from the USIM’s operator secret (EPS-AKA), not recoverable from a passive capture. User-plane encryption is optional per bearer; broadcast/paging are unprotected" } ], "reference": null, "layers": { "IG": { - "note": "Identify the cell and operator before any RF work — most of this is readable passively from what the network already broadcasts, no capture of user traffic. The goal is to know which operator’s cell you are looking at, on which band and bandwidth, and which identifiers and weaknesses are exposed in the clear. Treat all of this as licensed spectrum: receiving is one thing, but anything that transmits (Attack/App-layer steps) is for authorized testing on your own equipment only.", + "note": "Identify the cell and operator before any RF work, most of this is readable passively from what the network already broadcasts, no capture of user traffic. The goal is to know which operator’s cell you are looking at, on which band and bandwidth, and which identifiers and weaknesses are exposed in the clear. Treat all of this as licensed spectrum: receiving is one thing, but anything that transmits (Attack/App-layer steps) is for authorized testing on your own equipment only.", "lookFor": [ - "Band and EARFCN: which carrier frequency and band (e.g. B28/700 MHz, B20/800 MHz, B3/1800 MHz, B7/2.6 GHz) — this sets which radio can even tune it (a 1.766 GHz-capped RTL-SDR only reaches the low bands).", - "PCI (Physical Cell ID, 0–503) from PSS/SSS — the cell’s RF fingerprint, and how you tell neighbouring cells apart.", - "PLMN / operator identity (MCC+MNC) and TAC (Tracking Area Code) from SIB1 — which carrier owns the cell and which tracking area it sits in.", - "System bandwidth and frame config from the MIB on PBCH (1.4–20 MHz) — sets how wide a capture you need.", + "Band and EARFCN: which carrier frequency and band (e.g. B28/700 MHz, B20/800 MHz, B3/1800 MHz, B7/2.6 GHz), this sets which radio can even tune it (a 1.766 GHz-capped RTL-SDR only reaches the low bands).", + "PCI (Physical Cell ID, 0 to 503) from PSS/SSS, the cell’s RF fingerprint, and how you tell neighbouring cells apart.", + "PLMN / operator identity (MCC+MNC) and TAC (Tracking Area Code) from SIB1, which carrier owns the cell and which tracking area it sits in.", + "System bandwidth and frame config from the MIB on PBCH (1.4 to 20 MHz), sets how wide a capture you need.", "Known LTE/EPC weaknesses to cross-reference: pre-AKA messages are unauthenticated (the basis for IMSI catchers and fake-eNB downgrade/redirect), and SIB/paging leak configuration and S-TMSI in the clear.", - "Whether the cell pages with S-TMSI (normal) or ever falls back to IMSI (a privacy weakness) — visible on the paging channel." + "Whether the cell pages with S-TMSI (normal) or ever falls back to IMSI (a privacy weakness), visible on the paging channel." ] }, "SP": { - "note": "Where is the cell and how wide is it? LTE lives in narrow licensed slices scattered from ~700 MHz to 2.6 GHz, and a channel is 1.4–20 MHz wide. First find the carrier: sweep the candidate bands, spot the steady OFDM ‘wall’ of a downlink carrier, and read its centre frequency (EARFCN) and width on a waterfall. A 20 MHz LTE carrier fits inside one HackRF view; for clean OFDM symbol recovery later, a wider, well-clocked SDR helps. RTL-SDR works only for the low bands — it stops near 1.766 GHz, below the 1.8–2.6 GHz carriers. A commercial LTE modem gives a second, no-SDR route to the same answer: a SIMCom SIM7600 reports its serving (and, depending on firmware, neighbouring) cell over AT commands — AT+CPSI? reads the band, EARFCN, operator (MCC-MNC) and Cell ID straight off the chip.", + "note": "Where is the cell and how wide is it? LTE lives in narrow licensed slices scattered from ~700 MHz to 2.6 GHz, and a channel is 1.4 to 20 MHz wide. First find the carrier: sweep the candidate bands, spot the steady OFDM ‘wall’ of a downlink carrier, and read its centre frequency (EARFCN) and width on a waterfall. A 20 MHz LTE carrier fits inside one HackRF view; for clean OFDM symbol recovery later, a wider, well-clocked SDR helps. RTL-SDR works only for the low bands, it stops near 1.766 GHz, below the 1.8 to 2.6 GHz carriers. A commercial LTE modem gives a second, no-SDR route to the same answer: a SIMCom SIM7600 reports its serving (and, depending on firmware, neighbouring) cell over AT commands, AT+CPSI? reads the band, EARFCN, operator (MCC-MNC) and Cell ID straight off the chip.", "tools": [ - { "tool": "gqrx", "role": "Spectrum / waterfall view", "why": "See the live spectrum and find the LTE downlink carrier — read its centre frequency (EARFCN) and bandwidth before committing a capture tool. A 20 MHz carrier fits in one view on a HackRF; wider SDRs show more context.", "deps": ["hackrf-one", "bladerf-2-micro", "usrp-b210", "signalsdr-pro", "rtl-sdr-v4"], "caveat": "RTL-SDR V4 stops near 1.766 GHz — only the low LTE bands (e.g. 700/800 MHz), not the 1.8–2.6 GHz carriers." }, - { "tool": "sim7600", "role": "Modem cell scan (AT commands)", "why": "A commercial SIMCom LTE modem reports its serving cell — and, depending on firmware, neighbours — through its own AT command set: AT+CPSI? returns the system mode, operator (MCC-MNC), LAC/Cell ID, band and EARFCN. The fastest no-SDR way to see which cell a target is on and read its identity before committing capture hardware.", "deps": [], "needs": "A SIM7600 module on a USB/serial port driven from any AT terminal (or a short script). No SDR required; a valid/test SIM lets it register and report the live serving cell." } + { "tool": "gqrx", "role": "Spectrum / waterfall view", "why": "See the live spectrum and find the LTE downlink carrier, read its centre frequency (EARFCN) and bandwidth before committing a capture tool. A 20 MHz carrier fits in one view on a HackRF; wider SDRs show more context.", "deps": ["hackrf-one", "bladerf-2-micro", "usrp-b210", "signalsdr-pro", "rtl-sdr-v4"], "caveat": "RTL-SDR V4 stops near 1.766 GHz, only the low LTE bands (e.g. 700/800 MHz), not the 1.8 to 2.6 GHz carriers." }, + { "tool": "sim7600", "role": "Modem cell scan (AT commands)", "why": "A commercial SIMCom LTE modem reports its serving cell, and, depending on firmware, neighbours, through its own AT command set: AT+CPSI? returns the system mode, operator (MCC-MNC), LAC/Cell ID, band and EARFCN. The fastest no-SDR way to see which cell a target is on and read its identity before committing capture hardware.", "deps": [], "needs": "A SIM7600 module on a USB/serial port driven from any AT terminal (or a short script). No SDR required; a valid/test SIM lets it register and report the live serving cell." } ] }, "PHY": { - "note": "No standalone LTE demodulator in this kit. Recovering the OFDM grid — synchronising on PSS/SSS, finding the PCI, then decoding PBCH/PDCCH/PDSCH — and framing the result happen together inside the cell-search tools, so they live at the Capture step. The PHY job here is a coherent capture: LTE is OFDM, so frequency/timing drift smears the subcarrier grid. A disciplined-clock SDR (e.g. the USRP B210’s GPSDO option) gives the stable reference that makes blind PDCCH and full-grid decode reliable; a free-running HackRF can still do cell search and MIB/SIB but is twitchier on the control channel." + "note": "No standalone LTE demodulator in this kit. Recovering the OFDM grid, synchronising on PSS/SSS, finding the PCI, then decoding PBCH/PDCCH/PDSCH, and framing the result happen together inside the cell-search tools, so they live at the Capture step. The PHY job here is a coherent capture: LTE is OFDM, so frequency/timing drift smears the subcarrier grid. A disciplined-clock SDR (e.g. the USRP B210’s GPSDO option) gives the stable reference that makes blind PDCCH and full-grid decode reliable; a free-running HackRF can still do cell search and MIB/SIB but is twitchier on the control channel." }, "LL": { - "note": "Capture and decode the broadcast and control channels. Synchronise on the carrier, lock the PCI from PSS/SSS, decode the MIB on PBCH for bandwidth and frame number, then read the SIBs (PLMN, cell ID, TAC, scheduling) and watch paging. All of this is the network shouting in the clear — you are reading broadcast and control information, not user data. Pick a tool: srsRAN for an end-to-end cell-search + MIB/SIB receiver, FALCON or LTESniffer to focus on the PDCCH control channel, or gr-lte for a GNU Radio flowgraph. The captured RRC/MAC frames dissect in Wireshark over GSMTAP / MAC-LTE.", + "note": "Capture and decode the broadcast and control channels. Synchronise on the carrier, lock the PCI from PSS/SSS, decode the MIB on PBCH for bandwidth and frame number, then read the SIBs (PLMN, cell ID, TAC, scheduling) and watch paging. All of this is the network shouting in the clear, you are reading broadcast and control information, not user data. Pick a tool: srsRAN for an end-to-end cell-search + MIB/SIB receiver, FALCON or LTESniffer to focus on the PDCCH control channel, or gr-lte for a GNU Radio flowgraph. The captured RRC/MAC frames dissect in Wireshark over GSMTAP / MAC-LTE.", "decoder": "wireshark", "tools": [ - { "tool": "srsran-4g", "role": "Cell search + MIB/SIB receiver", "why": "srsUE’s cell-search and pcap modes do the full passive chain — PSS/SSS → PCI, MIB on PBCH (bandwidth, SFN), then SIB1+ (PLMN, cell ID, TAC) — and write a MAC-LTE/RRC PCAP. The reference open SDR LTE stack. Pick the SDR by how cleanly you need the OFDM grid: the GPSDO-disciplined USRP B210 is steadiest.", "deps": ["usrp-b210", "bladerf-2-micro", "signalsdr-pro", "hackrf-one"] }, - { "tool": "falcon", "role": "PDCCH control-channel analysis", "why": "Built on srsRAN to blind-decode the whole PDCCH in real time — every DCI/RNTI scheduling grant in the cell — exposing the live control-channel and resource-usage picture passively. The fastest way to see PDCCH activity.", "deps": ["usrp-b210", "bladerf-2-micro", "signalsdr-pro", "hackrf-one"], "caveat": "Research tool; needs a fast host. Blind PDCCH decode benefits from a disciplined-clock SDR." }, - { "tool": "ltesniffer", "role": "Downlink/uplink eavesdropper", "why": "Decodes PDCCH DCIs and the scheduled PDSCH/PUSCH for both directions of a cell, recovering RNTIs and per-UE scheduling — a focused passive eavesdropper for control and (unciphered) traffic exposure.", "deps": ["usrp-b210"], "caveat": "Authorised testing only — it recovers other users’ control/scheduling info. Wants a USRP-class disciplined radio; uplink capture needs the right RF setup." }, - { "tool": "gr-lte", "role": "GNU Radio LTE receiver", "why": "A GNU Radio flowgraph that synchronises, estimates the channel and decodes the PBCH end-to-end — the choice when you want to see and modify each DSP block of the receiver.", "deps": ["usrp-b210", "bladerf-2-micro", "hackrf-one"], "caveat": "Older codebase (last active ~2020); a learning/PBCH receiver rather than a full SIB/PDCCH suite." }, - { "tool": "qcsuper", "role": "Modem signalling capture → Wireshark", "why": "The SIM7600 is Qualcomm-based, so QCSuper can pull raw 2G/3G/4G radio frames (RRC/NAS, broadcast and paging) straight off its /dev/diag interface, wrap them in GSMTAP and stream a live PCAP into Wireshark — a real signalling capture from a ~US$25 modem, with no SDR cell-search to get right.", "deps": ["sim7600"], "needs": "A Qualcomm-based modem exposing the DIAG port (the SIM7600, or a rooted Qualcomm phone) and a registered/test SIM; it reads what the modem already receives — passive.", "caveat": "Captures the cellular control plane the modem sees — authorised testing only." } + { "tool": "srsran-4g", "role": "Cell search + MIB/SIB receiver", "why": "srsUE’s cell-search and pcap modes do the full passive chain, PSS/SSS → PCI, MIB on PBCH (bandwidth, SFN), then SIB1+ (PLMN, cell ID, TAC), and write a MAC-LTE/RRC PCAP. The reference open SDR LTE stack. Pick the SDR by how cleanly you need the OFDM grid: the GPSDO-disciplined USRP B210 is steadiest.", "deps": ["usrp-b210", "bladerf-2-micro", "signalsdr-pro", "hackrf-one"] }, + { "tool": "falcon", "role": "PDCCH control-channel analysis", "why": "Built on srsRAN to blind-decode the whole PDCCH in real time, every DCI/RNTI scheduling grant in the cell, exposing the live control-channel and resource-usage picture passively. The fastest way to see PDCCH activity.", "deps": ["usrp-b210", "bladerf-2-micro", "signalsdr-pro", "hackrf-one"], "caveat": "Research tool; needs a fast host. Blind PDCCH decode benefits from a disciplined-clock SDR." }, + { "tool": "ltesniffer", "role": "Downlink/uplink eavesdropper", "why": "Decodes PDCCH DCIs and the scheduled PDSCH/PUSCH for both directions of a cell, recovering RNTIs and per-UE scheduling, a focused passive eavesdropper for control and (unciphered) traffic exposure.", "deps": ["usrp-b210"], "caveat": "Authorised testing only, it recovers other users’ control/scheduling info. Wants a USRP-class disciplined radio; uplink capture needs the right RF setup." }, + { "tool": "gr-lte", "role": "GNU Radio LTE receiver", "why": "A GNU Radio flowgraph that synchronises, estimates the channel and decodes the PBCH end-to-end, the choice when you want to see and modify each DSP block of the receiver.", "deps": ["usrp-b210", "bladerf-2-micro", "hackrf-one"], "caveat": "Older codebase (last active ~2020); a learning/PBCH receiver rather than a full SIB/PDCCH suite." }, + { "tool": "qcsuper", "role": "Modem signalling capture → Wireshark", "why": "The SIM7600 is Qualcomm-based, so QCSuper can pull raw 2G/3G/4G radio frames (RRC/NAS, broadcast and paging) straight off its /dev/diag interface, wrap them in GSMTAP and stream a live PCAP into Wireshark, a real signalling capture from a ~US$25 modem, with no SDR cell-search to get right.", "deps": ["sim7600"], "needs": "A Qualcomm-based modem exposing the DIAG port (the SIM7600, or a rooted Qualcomm phone) and a registered/test SIM; it reads what the modem already receives, passive.", "caveat": "Captures the cellular control plane the modem sees, authorised testing only." } ] }, "CR": { - "note": "There is nothing to crack from a passive capture. The interesting LTE identifiers and configuration — PCI, PLMN, TAC, SIBs, paging S-TMSI, PDCCH scheduling — are broadcast or sent in the clear and are read, not decrypted, at the Capture step. The actual air-interface ciphering (SNOW 3G / AES / ZUC) and integrity protection are keyed by EPS-AKA from the secret on the USIM, shared only with the operator’s core; without that key a recording yields no session key offline, and there is no weak-pairing shortcut equivalent to BLE Just Works or WPA2. Recovering user-plane content means becoming the network (the Attack step) on equipment you are authorised to test, not breaking the ciphered capture." + "note": "There is nothing to crack from a passive capture. The interesting LTE identifiers and configuration, PCI, PLMN, TAC, SIBs, paging S-TMSI, PDCCH scheduling, are broadcast or sent in the clear and are read, not decrypted, at the Capture step. The actual air-interface ciphering (SNOW 3G / AES / ZUC) and integrity protection are keyed by EPS-AKA from the secret on the USIM, shared only with the operator’s core; without that key a recording yields no session key offline, and there is no weak-pairing shortcut equivalent to BLE Just Works or WPA2. Recovering user-plane content means becoming the network (the Attack step) on equipment you are authorised to test, not breaking the ciphered capture." }, "AT": { - "note": "Going active means transmitting in licensed cellular spectrum and impersonating a carrier — do this ONLY on your own equipment, with your own test SIMs, inside RF shielding (a Faraday enclosure or conducted setup), under an authorised test licence. Never radiate on a live operator’s band. The whole LTE attack surface here hangs off one rig: a rogue/fake eNodeB on a TX-capable SDR, broadcasting your own PCI/PLMN/SIBs on a test EARFCN at a higher level so your test UE reselects to it. From that foothold you exercise the weaknesses that live before authentication: (1) IMSI/identity exposure — the early NAS exchange is unauthenticated, so a fake cell can send an Identity Request and harvest the IMSI/IMEI; (2) downgrade / bidding-down — refuse or break the LTE attach (or set SIB redirection) to push the UE down to 2G/GSM where the crypto is far weaker; (3) signalling DoS / RRC attacks — RRC connection floods, attach floods and paging abuse against your own core to test resilience; (4) location/tracking — correlate paging (S-TMSI) and measurement reports to confirm a target UE’s presence in the cell. Pick a rogue-cell platform (srsRAN or OpenAirInterface), put a core behind it (Open5GS), watch the victim side with MobileInsight, and validate the attack is detectable with EFF’s Crocodile Hunter — or, portably, with EFF’s Rayhunter running on a cheap Qualcomm hotspot, which flags cell-site-simulator behaviour from the modem’s own control-plane feed with no SDR or host PC. Downgrade and signalling-flood techniques have no single dedicated public tool — they are configured on the srsRAN/OAI rogue cell and core, not a separate program.", + "note": "Going active means transmitting in licensed cellular spectrum and impersonating a carrier, do this ONLY on your own equipment, with your own test SIMs, inside RF shielding (a Faraday enclosure or conducted setup), under an authorised test licence. Never radiate on a live operator’s band. The whole LTE attack surface here hangs off one rig: a rogue/fake eNodeB on a TX-capable SDR, broadcasting your own PCI/PLMN/SIBs on a test EARFCN at a higher level so your test UE reselects to it. From that foothold you exercise the weaknesses that live before authentication: (1) IMSI/identity exposure, the early NAS exchange is unauthenticated, so a fake cell can send an Identity Request and harvest the IMSI/IMEI; (2) downgrade / bidding-down, refuse or break the LTE attach (or set SIB redirection) to push the UE down to 2G/GSM where the crypto is far weaker; (3) signalling DoS / RRC attacks, RRC connection floods, attach floods and paging abuse against your own core to test resilience; (4) location/tracking, correlate paging (S-TMSI) and measurement reports to confirm a target UE’s presence in the cell. Pick a rogue-cell platform (srsRAN or OpenAirInterface), put a core behind it (Open5GS), watch the victim side with MobileInsight, and validate the attack is detectable with EFF’s Crocodile Hunter, or, portably, with EFF’s Rayhunter running on a cheap Qualcomm hotspot, which flags cell-site-simulator behaviour from the modem’s own control-plane feed with no SDR or host PC. Downgrade and signalling-flood techniques have no single dedicated public tool, they are configured on the srsRAN/OAI rogue cell and core, not a separate program.", "tools": [ - { "tool": "srsran-4g", "role": "Rogue / test eNodeB", "why": "srsENB stands up a full LTE cell on an SDR — your own PCI, PLMN and SIBs on a test EARFCN — so a test UE camps and you can drive the attach/identity exchange, refuse the attach to force a 2G downgrade, or flood RRC/attach signalling. The reference platform for fake-eNB, IMSI-catcher and downgrade research.", "deps": ["usrp-b210", "bladerf-2-micro", "signalsdr-pro"], "needs": "A full-duplex TX-capable SDR (B210/bladeRF/SignalSDR), a test UE with a known/programmable SIM, and an EPC core (Open5GS or srsEPC) behind it. Authorised, RF-contained testing only.", "caveat": "Transmits in licensed spectrum — authorised lab/shielded use only." }, - { "tool": "imsi-catcher-srsran", "role": "Active IMSI catcher (srsRAN fork)", "why": "A small project that modifies srsENB into a turnkey active IMSI catcher: the fake cell lures the UE and issues an Identity Request, harvesting the IMSI over the unauthenticated pre-AKA NAS exchange — a concrete, ready-made instance of the identity-exposure attack rather than rolling it from the base stack.", "deps": ["usrp-b210", "bladerf-2-micro", "signalsdr-pro"], "needs": "Same rig as the srsRAN rogue cell (TX-capable SDR + test UE); it is a fork/patch of srsRAN_4G. Authorised, RF-contained testing only.", "caveat": "Small research repo built on srsRAN_4G; captures another device’s IMSI — authorised lab use only." }, - { "tool": "openairinterface5g", "role": "Alternative rogue eNodeB / RRC-NAS fuzzing", "why": "A second, independent full RAN+core stack: stand up the test/rogue cell on OAI when you want a different implementation to cross-check, or to drive RRC/NAS signalling and protocol fuzzing (malformed/flooded RRC and attach messages) that the srsRAN path doesn’t expose as cleanly.", "deps": ["usrp-b210", "bladerf-2-micro", "signalsdr-pro"], "needs": "A TX-capable SDR and a test UE; OAI can run its own core or pair with Open5GS. Authorised, RF-contained testing only.", "caveat": "Heavier build/tuning than srsRAN; transmits in licensed spectrum — authorised lab use only." }, - { "tool": "open5gs", "role": "EPC core behind the test cell", "why": "Provides the MME/HSS/SGW/PGW the eNodeB needs to run attach, authentication and NAS procedures end-to-end — so you control HSS subscriber data, steer the identity exchange, deny/break the attach to trigger a 2G downgrade, and absorb attach/RRC floods while you measure the core’s behaviour.", "deps": [], "needs": "Pure host software with no radio of its own — it sits behind the srsENB/OAI rogue cell over the S1 interface (the SDR belongs to the eNodeB). Configure it with your test PLMN and test-SIM credentials. Authorised testing only." }, - { "tool": "mobileinsight-core", "role": "Victim-side / paging & tracking analysis", "why": "Decodes the test UE’s own RRC, NAS, paging and measurement-report messages from its diagnostic feed, so you can confirm the attack from the victim’s side — see the Identity Request it answered, the redirect/downgrade it accepted, or correlate paging (S-TMSI) and measurements to prove location/tracking. Passive UE-side observation, no transmit.", "deps": [], "needs": "Runs on the test UE (a supported phone/modem exposing a diagnostic port) — it reads the device’s own control plane, so it bonds to the UE, not an SDR. Authorised testing of your own device only." }, - { "tool": "crocodilehunter", "role": "Fake-eNB detection / validation", "why": "EFF’s 4G IMSI-catcher detector: passively fingerprints fake eNodeBs (Stingray/Hailstorm class) from PCI/EARFCN/SIB anomalies. Run it alongside your rogue cell to prove the attack is detectable and to validate fake-base-station defences — the blue-team counterpart to the rest of this step.", "deps": ["usrp-b210", "bladerf-2-micro"], "needs": "A receive SDR (USRP B200/B210 or bladeRF) on a host running its srsRAN-based scanner. Passive monitoring only.", "caveat": "Built on srsRAN; original EFF repo is archived but is the reference 4G catcher-catcher." }, - { "tool": "rayhunter", "role": "Rogue-station detection (portable)", "why": "EFF’s IMSI-catcher detector running as firmware on a ~US$25 Qualcomm hotspot: it passively watches the LTE control plane from the modem’s /dev/diag feed and alerts on cell-site-simulator behaviour — unexpected identity/IMSI requests, downgrade attempts and suspicious tower configuration. Walk it through the cell to confirm whether a rogue station is present and to validate that your srsRAN/OAI fake-eNB test is detectable — the portable blue-team counterpart to Crocodile Hunter, with no SDR or host PC.", "deps": ["orbic-rc400l"], "needs": "A supported Qualcomm hotspot exposing /dev/diag (Orbic RC400L or TP-Link M7350) flashed with the Rayhunter firmware; its web UI shows live warnings. Passive — receive only.", "caveat": "Detection is heuristic (control-plane anomalies) — it flags suspicious behaviour, not a definitive verdict." } + { "tool": "srsran-4g", "role": "Rogue / test eNodeB", "why": "srsENB stands up a full LTE cell on an SDR, your own PCI, PLMN and SIBs on a test EARFCN, so a test UE camps and you can drive the attach/identity exchange, refuse the attach to force a 2G downgrade, or flood RRC/attach signalling. The reference platform for fake-eNB, IMSI-catcher and downgrade research.", "deps": ["usrp-b210", "bladerf-2-micro", "signalsdr-pro"], "needs": "A full-duplex TX-capable SDR (B210/bladeRF/SignalSDR), a test UE with a known/programmable SIM, and an EPC core (Open5GS or srsEPC) behind it. Authorised, RF-contained testing only.", "caveat": "Transmits in licensed spectrum, authorised lab/shielded use only." }, + { "tool": "imsi-catcher-srsran", "role": "Active IMSI catcher (srsRAN fork)", "why": "A small project that modifies srsENB into a turnkey active IMSI catcher: the fake cell lures the UE and issues an Identity Request, harvesting the IMSI over the unauthenticated pre-AKA NAS exchange, a concrete, ready-made instance of the identity-exposure attack rather than rolling it from the base stack.", "deps": ["usrp-b210", "bladerf-2-micro", "signalsdr-pro"], "needs": "Same rig as the srsRAN rogue cell (TX-capable SDR + test UE); it is a fork/patch of srsRAN_4G. Authorised, RF-contained testing only.", "caveat": "Small research repo built on srsRAN_4G; captures another device’s IMSI, authorised lab use only." }, + { "tool": "openairinterface5g", "role": "Alternative rogue eNodeB / RRC-NAS fuzzing", "why": "A second, independent full RAN+core stack: stand up the test/rogue cell on OAI when you want a different implementation to cross-check, or to drive RRC/NAS signalling and protocol fuzzing (malformed/flooded RRC and attach messages) that the srsRAN path doesn’t expose as cleanly.", "deps": ["usrp-b210", "bladerf-2-micro", "signalsdr-pro"], "needs": "A TX-capable SDR and a test UE; OAI can run its own core or pair with Open5GS. Authorised, RF-contained testing only.", "caveat": "Heavier build/tuning than srsRAN; transmits in licensed spectrum, authorised lab use only." }, + { "tool": "open5gs", "role": "EPC core behind the test cell", "why": "Provides the MME/HSS/SGW/PGW the eNodeB needs to run attach, authentication and NAS procedures end-to-end, so you control HSS subscriber data, steer the identity exchange, deny/break the attach to trigger a 2G downgrade, and absorb attach/RRC floods while you measure the core’s behaviour.", "deps": [], "needs": "Pure host software with no radio of its own, it sits behind the srsENB/OAI rogue cell over the S1 interface (the SDR belongs to the eNodeB). Configure it with your test PLMN and test-SIM credentials. Authorised testing only." }, + { "tool": "mobileinsight-core", "role": "Victim-side / paging & tracking analysis", "why": "Decodes the test UE’s own RRC, NAS, paging and measurement-report messages from its diagnostic feed, so you can confirm the attack from the victim’s side, see the Identity Request it answered, the redirect/downgrade it accepted, or correlate paging (S-TMSI) and measurements to prove location/tracking. Passive UE-side observation, no transmit.", "deps": [], "needs": "Runs on the test UE (a supported phone/modem exposing a diagnostic port), it reads the device’s own control plane, so it bonds to the UE, not an SDR. Authorised testing of your own device only." }, + { "tool": "crocodilehunter", "role": "Fake-eNB detection / validation", "why": "EFF’s 4G IMSI-catcher detector: passively fingerprints fake eNodeBs (Stingray/Hailstorm class) from PCI/EARFCN/SIB anomalies. Run it alongside your rogue cell to prove the attack is detectable and to validate fake-base-station defences, the blue-team counterpart to the rest of this step.", "deps": ["usrp-b210", "bladerf-2-micro"], "needs": "A receive SDR (USRP B200/B210 or bladeRF) on a host running its srsRAN-based scanner. Passive monitoring only.", "caveat": "Built on srsRAN; original EFF repo is archived but is the reference 4G catcher-catcher." }, + { "tool": "rayhunter", "role": "Rogue-station detection (portable)", "why": "EFF’s IMSI-catcher detector running as firmware on a ~US$25 Qualcomm hotspot: it passively watches the LTE control plane from the modem’s /dev/diag feed and alerts on cell-site-simulator behaviour, unexpected identity/IMSI requests, downgrade attempts and suspicious tower configuration. Walk it through the cell to confirm whether a rogue station is present and to validate that your srsRAN/OAI fake-eNB test is detectable, the portable blue-team counterpart to Crocodile Hunter, with no SDR or host PC.", "deps": ["orbic-rc400l"], "needs": "A supported Qualcomm hotspot exposing /dev/diag (Orbic RC400L or TP-Link M7350) flashed with the Rayhunter firmware; its web UI shows live warnings. Passive, receive only.", "caveat": "Detection is heuristic (control-plane anomalies), it flags suspicious behaviour, not a definitive verdict." } ] }, "AP": { - "note": "Above the air link, LTE’s ‘application layer’ is the NAS / EPC signalling — attach, authentication, identity and tracking-area procedures between the UE and the core. You can only exercise these by being the network: with your own eNodeB + core (the Attack step) and an authorised test UE, drive and inspect the NAS exchange — watch the IMSI/S-TMSI handling, force re-authentication or identity requests, and test how the device behaves under hostile core signalling. This is end-to-end control-plane testing of the device-to-network trust, done on equipment you own and are authorised to operate.", + "note": "Above the air link, LTE’s ‘application layer’ is the NAS / EPC signalling, attach, authentication, identity and tracking-area procedures between the UE and the core. You can only exercise these by being the network: with your own eNodeB + core (the Attack step) and an authorised test UE, drive and inspect the NAS exchange, watch the IMSI/S-TMSI handling, force re-authentication or identity requests, and test how the device behaves under hostile core signalling. This is end-to-end control-plane testing of the device-to-network trust, done on equipment you own and are authorised to operate.", "tools": [ - { "tool": "open5gs", "role": "EPC / NAS test harness", "why": "A full EPC (MME/HSS/SGW/PGW) you control: provision test subscribers in the HSS and drive the attach/auth/identity NAS procedures to probe how a UE handles the control plane — the platform for app-/control-layer LTE testing once your own cell is up.", "deps": [], "needs": "Host software with no radio of its own — pairs with the srsRAN rogue/test eNodeB (which supplies the TX-capable SDR); configure your test PLMN and test-SIM credentials. Authorised testing only.", "caveat": "Requires running your own radiating cell — authorised, RF-contained use only." } + { "tool": "open5gs", "role": "EPC / NAS test harness", "why": "A full EPC (MME/HSS/SGW/PGW) you control: provision test subscribers in the HSS and drive the attach/auth/identity NAS procedures to probe how a UE handles the control plane, the platform for app-/control-layer LTE testing once your own cell is up.", "deps": [], "needs": "Host software with no radio of its own, pairs with the srsRAN rogue/test eNodeB (which supplies the TX-capable SDR); configure your test PLMN and test-SIM credentials. Authorised testing only.", "caveat": "Requires running your own radiating cell, authorised, RF-contained use only." } ] } } diff --git a/src/data/toolchains/nr5g.js b/src/data/toolchains/nr5g.js index 86cd6f4..fafc45a 100644 --- a/src/data/toolchains/nr5g.js +++ b/src/data/toolchains/nr5g.js @@ -1,68 +1,68 @@ export default { "status": "complete", "facts": [ - { "k": "Band", "v": "Licensed cellular, two ranges: FR1 sub-6 GHz (~410 MHz–7.125 GHz; common bands n1/2100, n3/1800, n78/3.5 GHz, n28/700) and FR2 mmWave (~24.25–52.6 GHz). FDD and TDD; n78 (and most mid-band) is TDD" }, + { "k": "Band", "v": "Licensed cellular, two ranges: FR1 sub-6 GHz (~410 MHz to 7.125 GHz; common bands n1/2100, n3/1800, n78/3.5 GHz, n28/700) and FR2 mmWave (~24.25 to 52.6 GHz). FDD and TDD; n78 (and most mid-band) is TDD" }, { "k": "Bandwidth", "v": "Flexible numerology: subcarrier spacing 15·2^μ kHz (15/30/60/120 kHz). A carrier reaches up to 100 MHz in FR1 and 400 MHz in FR2; identified by its NR-ARFCN. Sub-6 carriers fit a USRP/bladeRF; FR2 does not (see caveats)" }, { "k": "Modulation", "v": "CP-OFDM on both downlink and uplink (uplink can also use DFT-s-OFDM); QPSK/16/64/256-QAM. Unlike LTE, the uplink is OFDM-based too" }, - { "k": "Cell ID", "v": "PSS gives N_ID(2) (0–2), SSS gives N_ID(1) (0–335); PCI = 3·N_ID(1) + N_ID(2) → 1008 physical cell IDs (0–1007). Carried in the SS/PBCH block (SSB) used for cell search" }, + { "k": "Cell ID", "v": "PSS gives N_ID(2) (0 to 2), SSS gives N_ID(1) (0 to 335); PCI = 3·N_ID(1) + N_ID(2) → 1008 physical cell IDs (0 to 1007). Carried in the SS/PBCH block (SSB) used for cell search" }, { "k": "Broadcast", "v": "MIB on PBCH inside the SSB (SFN, SSB position, SIB1 scheduling); SIB1 on PDSCH carries PLMN, cell identity, TAC and access info. SIBs are broadcast in the clear, as in LTE" }, { "k": "Architecture", "v": "SA (Standalone) = 5G NR + 5G Core (AMF/SMF/UPF); NSA (Non-Standalone) = 5G NR carrier anchored to an LTE eNB + EPC. Knowing SA vs NSA tells you whether there is a 5G core to talk to at all" }, - { "k": "Security", "v": "5G-AKA keyed from the USIM operator secret — like LTE, no offline shortcut from a passive capture. Improvement over LTE: the long-term identity (SUPI/IMSI) is concealed as a SUCI (ECIES public-key encryption), so it is no longer sent in the clear on the air" } + { "k": "Security", "v": "5G-AKA keyed from the USIM operator secret, like LTE, no offline shortcut from a passive capture. Improvement over LTE: the long-term identity (SUPI/IMSI) is concealed as a SUCI (ECIES public-key encryption), so it is no longer sent in the clear on the air" } ], "reference": null, "layers": { "IG": { - "note": "Identify the cell, operator and 5G mode before any RF work — most of this is readable passively from what the network already broadcasts, no capture of user traffic. The goal is to know which operator’s cell you are looking at, on which band and bandwidth, whether it is Standalone (its own 5G core) or Non-Standalone (a 5G carrier bolted onto an LTE anchor), and which identifiers are exposed in the clear. The descent mirrors LTE and reuses the same tools; the differences are the wider/higher bands, the SSB-based cell search, and that the subscriber’s long-term identity is now concealed as a SUCI. Treat all of this as licensed spectrum: receiving is one thing, but anything that transmits (Attack/App-layer steps) is for authorised testing on your own equipment only.", + "note": "Identify the cell, operator and 5G mode before any RF work, most of this is readable passively from what the network already broadcasts, no capture of user traffic. The goal is to know which operator’s cell you are looking at, on which band and bandwidth, whether it is Standalone (its own 5G core) or Non-Standalone (a 5G carrier bolted onto an LTE anchor), and which identifiers are exposed in the clear. The descent mirrors LTE and reuses the same tools; the differences are the wider/higher bands, the SSB-based cell search, and that the subscriber’s long-term identity is now concealed as a SUCI. Treat all of this as licensed spectrum: receiving is one thing, but anything that transmits (Attack/App-layer steps) is for authorised testing on your own equipment only.", "lookFor": [ - "Band and NR-ARFCN: which carrier frequency and band (e.g. n78/3.3–3.8 GHz TDD, n1/2100, n3/1800, n28/700) — this sets which radio can even tune it. A USRP-class SDR reaches FR1; FR2 mmWave (n257/n258/n260, ~24–40 GHz) is out of reach of common SDRs.", + "Band and NR-ARFCN: which carrier frequency and band (e.g. n78/3.3 to 3.8 GHz TDD, n1/2100, n3/1800, n28/700), this sets which radio can even tune it. A USRP-class SDR reaches FR1; FR2 mmWave (n257/n258/n260, ~24 to 40 GHz) is out of reach of common SDRs.", "SA vs NSA: is this a Standalone 5G cell (its own 5G core, NGAP/NAS-5GS) or Non-Standalone (5G NR carrier anchored to an LTE eNB + EPC)? This decides whether there is a 5G core to interact with, or whether the control plane still rides LTE.", - "PCI (Physical Cell ID, 0–1007) from PSS/SSS in the SSB — the cell’s RF fingerprint and how you tell neighbouring cells apart (1008 IDs vs LTE’s 504).", - "PLMN / operator identity (MCC+MNC) and TAC from SIB1 — which carrier owns the cell and which tracking area it sits in.", - "Numerology and bandwidth from the SSB/SIB1 (subcarrier spacing 15/30/60 kHz, carrier up to 100 MHz in FR1) — sets how wide and how fast a capture you need.", - "Known 5G weaknesses to cross-reference: SIB/paging are still broadcast in the clear; pre-authentication NAS/RRC remains a documented attack surface (rogue gNB, baseband fuzzing — e.g. the 5Ghoul class of bugs). Note the SUPI is now hidden as a SUCI, closing the LTE-style cleartext IMSI exposure on the air." + "PCI (Physical Cell ID, 0 to 1007) from PSS/SSS in the SSB, the cell’s RF fingerprint and how you tell neighbouring cells apart (1008 IDs vs LTE’s 504).", + "PLMN / operator identity (MCC+MNC) and TAC from SIB1, which carrier owns the cell and which tracking area it sits in.", + "Numerology and bandwidth from the SSB/SIB1 (subcarrier spacing 15/30/60 kHz, carrier up to 100 MHz in FR1), sets how wide and how fast a capture you need.", + "Known 5G weaknesses to cross-reference: SIB/paging are still broadcast in the clear; pre-authentication NAS/RRC remains a documented attack surface (rogue gNB, baseband fuzzing, e.g. the 5Ghoul class of bugs). Note the SUPI is now hidden as a SUCI, closing the LTE-style cleartext IMSI exposure on the air." ] }, "SP": { - "note": "Where is the cell and how wide is it? 5G FR1 lives in licensed slices scattered from ~700 MHz to ~3.8 GHz, and a carrier can be up to 100 MHz wide — wider than any LTE channel. First find the carrier: sweep the candidate bands, spot the SSB and the OFDM ‘wall’ of a downlink carrier, and read its centre frequency (NR-ARFCN) and width on a waterfall. A 100 MHz n78 carrier exceeds a single HackRF view (~20 MHz) and even a standard USRP B210 (~56 MHz) — you see a slice, enough to locate the SSB; a wider, well-clocked SDR shows more of the carrier. FR2 mmWave (~24–40 GHz) is effectively invisible to these radios: their tuners stop at 6 GHz, so confirming an FR2 cell needs a mmWave front-end or a commercial scanner, not the SDRs in this kit. A commercial 5G modem gives a second, no-SDR route to the serving-cell answer — a Qualcomm-based 5G modem reports its band, NR-ARFCN, operator and cell over its diagnostic/AT interface.", + "note": "Where is the cell and how wide is it? 5G FR1 lives in licensed slices scattered from ~700 MHz to ~3.8 GHz, and a carrier can be up to 100 MHz wide, wider than any LTE channel. First find the carrier: sweep the candidate bands, spot the SSB and the OFDM ‘wall’ of a downlink carrier, and read its centre frequency (NR-ARFCN) and width on a waterfall. A 100 MHz n78 carrier exceeds a single HackRF view (~20 MHz) and even a standard USRP B210 (~56 MHz), you see a slice, enough to locate the SSB; a wider, well-clocked SDR shows more of the carrier. FR2 mmWave (~24 to 40 GHz) is effectively invisible to these radios: their tuners stop at 6 GHz, so confirming an FR2 cell needs a mmWave front-end or a commercial scanner, not the SDRs in this kit. A commercial 5G modem gives a second, no-SDR route to the serving-cell answer, a Qualcomm-based 5G modem reports its band, NR-ARFCN, operator and cell over its diagnostic/AT interface.", "tools": [ - { "tool": "gqrx", "role": "Spectrum / waterfall view", "why": "See the live spectrum and find the 5G downlink carrier and its SSB — read the centre frequency (NR-ARFCN) and gauge the bandwidth before committing a capture tool. A wide FR1 carrier (up to 100 MHz) won’t fit one view; you locate the SSB and the carrier edges. Sub-6 GHz only.", "deps": ["hackrf-one", "bladerf-2-micro", "usrp-b210", "signalsdr-pro"], "caveat": "Sub-6 GHz (FR1) only — none of these tuners reach FR2 mmWave (~24–40 GHz). A single HackRF/B210 view is narrower than a 100 MHz n78 carrier." }, - { "tool": "qcsuper", "role": "Modem cell scan / signalling → Wireshark", "why": "A Qualcomm-based 5G modem reports the serving cell over its DIAG interface, and QCSuper can pull raw 5G (and 2G/3G/4G) radio frames straight off /dev/diag, wrap them in GSMTAP and stream a PCAP into Wireshark — the fastest no-SDR way to see which cell a target is on and read its identity before committing capture hardware.", "deps": ["quectel-rm500q"], "needs": "A Qualcomm-based 5G modem (e.g. Quectel RM500Q) or a rooted Qualcomm phone exposing the DIAG port, plus a registered/test SIM; it reads what the modem already receives — passive. 5G frame support depends on the specific modem/firmware.", "caveat": "Reads the cellular control plane the modem sees — authorised testing only; 5G capture is modem-dependent." } + { "tool": "gqrx", "role": "Spectrum / waterfall view", "why": "See the live spectrum and find the 5G downlink carrier and its SSB, read the centre frequency (NR-ARFCN) and gauge the bandwidth before committing a capture tool. A wide FR1 carrier (up to 100 MHz) won’t fit one view; you locate the SSB and the carrier edges. Sub-6 GHz only.", "deps": ["hackrf-one", "bladerf-2-micro", "usrp-b210", "signalsdr-pro"], "caveat": "Sub-6 GHz (FR1) only, none of these tuners reach FR2 mmWave (~24 to 40 GHz). A single HackRF/B210 view is narrower than a 100 MHz n78 carrier." }, + { "tool": "qcsuper", "role": "Modem cell scan / signalling → Wireshark", "why": "A Qualcomm-based 5G modem reports the serving cell over its DIAG interface, and QCSuper can pull raw 5G (and 2G/3G/4G) radio frames straight off /dev/diag, wrap them in GSMTAP and stream a PCAP into Wireshark, the fastest no-SDR way to see which cell a target is on and read its identity before committing capture hardware.", "deps": ["quectel-rm500q"], "needs": "A Qualcomm-based 5G modem (e.g. Quectel RM500Q) or a rooted Qualcomm phone exposing the DIAG port, plus a registered/test SIM; it reads what the modem already receives, passive. 5G frame support depends on the specific modem/firmware.", "caveat": "Reads the cellular control plane the modem sees, authorised testing only; 5G capture is modem-dependent." } ] }, "PHY": { - "note": "No standalone 5G NR demodulator in this kit. Recovering the OFDM grid — synchronising on the SSB (PSS/SSS → PCI), decoding the MIB on PBCH, then SIB1 and the control channels — happens together inside the cell-search tools, so it lives at the Capture step. The PHY job here is a coherent capture: 5G is CP-OFDM with flexible numerology, so frequency/timing drift smears the subcarrier grid, and the wider carrier and higher TDD bands (n78) demand more of the radio than LTE did. A disciplined-clock SDR (e.g. the USRP B210’s GPSDO option) gives the stable reference that makes SSB lock and full-grid decode reliable; a free-running HackRF is twitchier. Note that passive 5G air decoding is far less mature than LTE — there is no srsUE-style turnkey passive SA receiver, and the sniffers below are research-grade (see the Capture step)." + "note": "No standalone 5G NR demodulator in this kit. Recovering the OFDM grid, synchronising on the SSB (PSS/SSS → PCI), decoding the MIB on PBCH, then SIB1 and the control channels, happens together inside the cell-search tools, so it lives at the Capture step. The PHY job here is a coherent capture: 5G is CP-OFDM with flexible numerology, so frequency/timing drift smears the subcarrier grid, and the wider carrier and higher TDD bands (n78) demand more of the radio than LTE did. A disciplined-clock SDR (e.g. the USRP B210’s GPSDO option) gives the stable reference that makes SSB lock and full-grid decode reliable; a free-running HackRF is twitchier. Note that passive 5G air decoding is far less mature than LTE, there is no srsUE-style turnkey passive SA receiver, and the sniffers below are research-grade (see the Capture step)." }, "LL": { - "note": "Capture and decode the broadcast and control channels — but be honest that passive 5G NR air-sniffing is immature and research-grade compared with LTE. There is no drop-in passive SA receiver equivalent to srsUE’s LTE cell-search: the practical routes are (1) stand up your own gNB+UE link with srsRAN Project or OpenAirInterface and read the SSB/MIB/SIB1 from a controlled cell, (2) use a research PDCCH decoder (5GSniffer) or a research sniffer/injector (Sni5Gect) to recover control-channel/MAC activity passively from a real cell — both are srsRAN-based, FR1/sub-6, and demanding on host and setup, and (3) the no-SDR modem route: QCSuper pulls 5G signalling off a Qualcomm modem’s DIAG port. Captured NGAP/NAS-5GS and MAC-NR frames dissect in Wireshark.", + "note": "Capture and decode the broadcast and control channels, but be honest that passive 5G NR air-sniffing is immature and research-grade compared with LTE. There is no drop-in passive SA receiver equivalent to srsUE’s LTE cell-search: the practical routes are (1) stand up your own gNB+UE link with srsRAN Project or OpenAirInterface and read the SSB/MIB/SIB1 from a controlled cell, (2) use a research PDCCH decoder (5GSniffer) or a research sniffer/injector (Sni5Gect) to recover control-channel/MAC activity passively from a real cell, both are srsRAN-based, FR1/sub-6, and demanding on host and setup, and (3) the no-SDR modem route: QCSuper pulls 5G signalling off a Qualcomm modem’s DIAG port. Captured NGAP/NAS-5GS and MAC-NR frames dissect in Wireshark.", "decoder": "wireshark", "tools": [ - { "tool": "srsran-project", "role": "Cell search via your own gNB", "why": "SRS’s 5G CU/DU stack stands up a 5G NR gNB on an SDR; paired with a 5G core and a test UE it gives you a controlled SA link whose SSB/MIB/SIB1 and NGAP you can read end-to-end — the practical way to study 5G cell search when no turnkey passive SA receiver exists. Pick the SDR by how cleanly you need the OFDM grid; the GPSDO-disciplined USRP B210 is steadiest.", "deps": ["usrp-b210", "bladerf-2-micro", "signalsdr-pro"], "needs": "Pairs with a 5G core (Open5GS or free5GC) and a test UE/SIM; sub-6 (FR1) on a USRP-class SDR. For a controlled lab cell, not a passive receiver for an operator’s network.", "caveat": "The srsRAN_Project (5G) GitHub repo is archived — check srsran.com for the current distribution. Standing up a radiating gNB transmits in licensed spectrum — authorised, RF-contained use only." }, - { "tool": "5gsniffer", "role": "PDCCH / DCI passive decoder", "why": "Blind-decodes the 5G PDCCH to recover the DCIs and the RNTIs active in a cell — a passive view of scheduling/identity activity, the closest 5G equivalent to LTE’s FALCON. srsRAN-based, FR1 FDD.", "deps": ["usrp-b210", "bladerf-2-micro"], "needs": "An SDR (USRP B210/X310 or bladeRF), or a recorded I/Q file — the current release recommends working from a recording, and live SDR capture needs extra setup.", "caveat": "Research-grade and FDD/sub-6 only; not a turnkey receiver. Passive control-channel analysis, authorised testing only." }, - { "tool": "sni5gect", "role": "MAC-NR sniffer (research)", "why": "Passively captures unencrypted MAC-NR messages between a gNB and a UE and dissects them in Wireshark — a real over-the-air 5G sniffer (also capable of downlink injection, see the Attack step). The most capable open passive 5G NR sniffer, but heavy.", "deps": ["usrp-b210"], "needs": "A USRP B210/X310, Ubuntu 22.04 and a strong host (12-core/16 GB). Recovers another link’s control messages — authorised testing only.", "caveat": "Research framework, FR1/sub-6, demanding setup; captures messages between other parties — authorised use only." }, - { "tool": "qcsuper", "role": "Modem signalling capture → Wireshark", "why": "Pulls raw 5G (and 2G/3G/4G) radio frames straight off a Qualcomm 5G modem’s /dev/diag interface, wraps them in GSMTAP and streams a live PCAP into Wireshark — a real signalling capture from a commercial modem, with no SDR cell-search to get right. The most reliable everyday route to 5G control-plane frames.", "deps": ["quectel-rm500q"], "needs": "A Qualcomm-based 5G modem (e.g. Quectel RM500Q) or a rooted Qualcomm phone exposing the DIAG port and a registered/test SIM; it reads what the modem already receives — passive. 5G support is modem/firmware-dependent.", "caveat": "Captures the cellular control plane the modem sees — authorised testing only." } + { "tool": "srsran-project", "role": "Cell search via your own gNB", "why": "SRS’s 5G CU/DU stack stands up a 5G NR gNB on an SDR; paired with a 5G core and a test UE it gives you a controlled SA link whose SSB/MIB/SIB1 and NGAP you can read end-to-end, the practical way to study 5G cell search when no turnkey passive SA receiver exists. Pick the SDR by how cleanly you need the OFDM grid; the GPSDO-disciplined USRP B210 is steadiest.", "deps": ["usrp-b210", "bladerf-2-micro", "signalsdr-pro"], "needs": "Pairs with a 5G core (Open5GS or free5GC) and a test UE/SIM; sub-6 (FR1) on a USRP-class SDR. For a controlled lab cell, not a passive receiver for an operator’s network.", "caveat": "The srsRAN_Project (5G) GitHub repo is archived, check srsran.com for the current distribution. Standing up a radiating gNB transmits in licensed spectrum, authorised, RF-contained use only." }, + { "tool": "5gsniffer", "role": "PDCCH / DCI passive decoder", "why": "Blind-decodes the 5G PDCCH to recover the DCIs and the RNTIs active in a cell, a passive view of scheduling/identity activity, the closest 5G equivalent to LTE’s FALCON. srsRAN-based, FR1 FDD.", "deps": ["usrp-b210", "bladerf-2-micro"], "needs": "An SDR (USRP B210/X310 or bladeRF), or a recorded I/Q file, the current release recommends working from a recording, and live SDR capture needs extra setup.", "caveat": "Research-grade and FDD/sub-6 only; not a turnkey receiver. Passive control-channel analysis, authorised testing only." }, + { "tool": "sni5gect", "role": "MAC-NR sniffer (research)", "why": "Passively captures unencrypted MAC-NR messages between a gNB and a UE and dissects them in Wireshark, a real over-the-air 5G sniffer (also capable of downlink injection, see the Attack step). The most capable open passive 5G NR sniffer, but heavy.", "deps": ["usrp-b210"], "needs": "A USRP B210/X310, Ubuntu 22.04 and a strong host (12-core/16 GB). Recovers another link’s control messages, authorised testing only.", "caveat": "Research framework, FR1/sub-6, demanding setup; captures messages between other parties, authorised use only." }, + { "tool": "qcsuper", "role": "Modem signalling capture → Wireshark", "why": "Pulls raw 5G (and 2G/3G/4G) radio frames straight off a Qualcomm 5G modem’s /dev/diag interface, wraps them in GSMTAP and streams a live PCAP into Wireshark, a real signalling capture from a commercial modem, with no SDR cell-search to get right. The most reliable everyday route to 5G control-plane frames.", "deps": ["quectel-rm500q"], "needs": "A Qualcomm-based 5G modem (e.g. Quectel RM500Q) or a rooted Qualcomm phone exposing the DIAG port and a registered/test SIM; it reads what the modem already receives, passive. 5G support is modem/firmware-dependent.", "caveat": "Captures the cellular control plane the modem sees, authorised testing only." } ] }, "CR": { - "note": "There is nothing to crack from a passive capture, exactly as in LTE. The interesting 5G identifiers and configuration — PCI, PLMN, TAC, SIBs, paging, PDCCH scheduling — are broadcast or sent in the clear and are read, not decrypted, at the Capture step. The air-interface ciphering and integrity (NEA/NIA: SNOW 3G / AES / ZUC) are keyed by 5G-AKA from the secret on the USIM, shared only with the operator’s core; without that key a recording yields no session key offline, and there is no weak-pairing shortcut. 5G actually improves on LTE here: the long-term identity (SUPI/IMSI) is no longer sent in the clear — it is concealed as a SUCI using the home network’s public key (ECIES), so the LTE-style passive IMSI harvest off the air is closed. Recovering user-plane content still means becoming the network (the Attack step) on equipment you are authorised to test, not breaking the ciphered capture." + "note": "There is nothing to crack from a passive capture, exactly as in LTE. The interesting 5G identifiers and configuration, PCI, PLMN, TAC, SIBs, paging, PDCCH scheduling, are broadcast or sent in the clear and are read, not decrypted, at the Capture step. The air-interface ciphering and integrity (NEA/NIA: SNOW 3G / AES / ZUC) are keyed by 5G-AKA from the secret on the USIM, shared only with the operator’s core; without that key a recording yields no session key offline, and there is no weak-pairing shortcut. 5G actually improves on LTE here: the long-term identity (SUPI/IMSI) is no longer sent in the clear, it is concealed as a SUCI using the home network’s public key (ECIES), so the LTE-style passive IMSI harvest off the air is closed. Recovering user-plane content still means becoming the network (the Attack step) on equipment you are authorised to test, not breaking the ciphered capture." }, "AT": { - "note": "Going active means transmitting in licensed cellular spectrum and impersonating a carrier — do this ONLY on your own equipment, with your own test SIMs, inside RF shielding (a Faraday enclosure or conducted setup), under an authorised test licence. Never radiate on a live operator’s band. As in LTE, the 5G attack surface here hangs off one rig: a rogue/fake gNB on a TX-capable SDR broadcasting your own PCI/PLMN/SIBs on a test NR-ARFCN, with a 5G core behind it, so your test UE camps and you can drive the pre-authentication NAS/RRC exchange. From that foothold you exercise the weaknesses that live before authentication: identity/registration handling (now harder to abuse because the SUPI is concealed as a SUCI — note the shift from LTE’s cleartext IMSI — so there is no native 5G IMSI catcher: the SUCI closes the LTE-style passive/fake-cell harvest, and the practical identity attack is to DOWNGRADE the UE to LTE or 2G with the rogue cell and run the IMSI catcher there, see the LTE and GSM wayfinders), downgrade/bidding-down, signalling DoS, and RRC/NAS protocol fuzzing. Pick a rogue-cell platform (srsRAN Project or OpenAirInterface) with a 5G core (Open5GS or free5GC) behind it. For baseband resilience, 5Ghoul drives a malicious OAI gNB with a set of pre-auth RRC/NAS bugs and a fuzzer against COTS Qualcomm/MediaTek phones; for MAC-NR injection without a rogue base station, Sni5Gect injects crafted downlink messages at specific connection states; and 5Greplay fuzzes/replays captured 5G control-plane traffic against your own core (AMF/SMF over NGAP) rather than over the air.", + "note": "Going active means transmitting in licensed cellular spectrum and impersonating a carrier, do this ONLY on your own equipment, with your own test SIMs, inside RF shielding (a Faraday enclosure or conducted setup), under an authorised test licence. Never radiate on a live operator’s band. As in LTE, the 5G attack surface here hangs off one rig: a rogue/fake gNB on a TX-capable SDR broadcasting your own PCI/PLMN/SIBs on a test NR-ARFCN, with a 5G core behind it, so your test UE camps and you can drive the pre-authentication NAS/RRC exchange. From that foothold you exercise the weaknesses that live before authentication: identity/registration handling (now harder to abuse because the SUPI is concealed as a SUCI, note the shift from LTE’s cleartext IMSI, so there is no native 5G IMSI catcher: the SUCI closes the LTE-style passive/fake-cell harvest, and the practical identity attack is to DOWNGRADE the UE to LTE or 2G with the rogue cell and run the IMSI catcher there, see the LTE and GSM wayfinders), downgrade/bidding-down, signalling DoS, and RRC/NAS protocol fuzzing. Pick a rogue-cell platform (srsRAN Project or OpenAirInterface) with a 5G core (Open5GS or free5GC) behind it. For baseband resilience, 5Ghoul drives a malicious OAI gNB with a set of pre-auth RRC/NAS bugs and a fuzzer against COTS Qualcomm/MediaTek phones; for MAC-NR injection without a rogue base station, Sni5Gect injects crafted downlink messages at specific connection states; and 5Greplay fuzzes/replays captured 5G control-plane traffic against your own core (AMF/SMF over NGAP) rather than over the air.", "tools": [ - { "tool": "srsran-project", "role": "Rogue / test gNB", "why": "Stands up a full 5G NR gNB (CU/DU) on an SDR — your own PCI, PLMN and SIBs on a test NR-ARFCN — so a test UE camps and you can drive the registration/identity exchange, attempt downgrade, or flood RRC/NAS signalling. The reference open platform for fake-gNB and 5G rogue-cell research.", "deps": ["usrp-b210", "bladerf-2-micro", "signalsdr-pro"], "needs": "A full-duplex TX-capable SDR (B210/bladeRF/SignalSDR), a test UE with a known/programmable 5G SIM, and a 5G core (Open5GS or free5GC) behind it. FR1/sub-6. Authorised, RF-contained testing only.", "caveat": "The srsRAN_Project (5G) GitHub repo is archived — check srsran.com for current builds. Transmits in licensed spectrum — authorised lab/shielded use only." }, - { "tool": "openairinterface5g", "role": "Alternative rogue gNB / RRC-NAS fuzzing", "why": "A second, independent full 5G RAN+core stack: stand up the test/rogue gNB on OAI when you want a different implementation to cross-check, or to drive RRC/NAS signalling and protocol fuzzing that the srsRAN path doesn’t expose as cleanly. It is also the gNB platform that 5Ghoul builds on.", "deps": ["usrp-b210", "bladerf-2-micro", "signalsdr-pro"], "needs": "A TX-capable SDR and a test UE; OAI runs its own 5G core or pairs with Open5GS/free5GC. FR1/sub-6. Authorised, RF-contained testing only.", "caveat": "Heavier build/tuning than srsRAN; transmits in licensed spectrum — authorised lab use only." }, - { "tool": "5ghoul", "role": "Baseband attack / fuzzing (worked example)", "why": "A ready-made set of pre-authentication 5G NR RRC/NAS vulnerabilities plus a fuzzer that drives a malicious OAI gNB to crash or disrupt COTS Qualcomm/MediaTek smartphone basebands — a concrete, turnkey instance of the rogue-gNB baseband-attack surface rather than rolling it from the base stack.", "deps": ["usrp-b210", "bladerf-2-micro", "signalsdr-pro"], "needs": "Runs on an OpenAirInterface gNB with a TX-capable SDR and a target UE; FR1/sub-6. Authorised, RF-contained testing of your own device only.", "caveat": "Built on OAI; disrupts real basebands — authorised lab/shielded use only." }, - { "tool": "sni5gect", "role": "MAC-NR downlink injection", "why": "Injects crafted MAC-NR downlink packets to a target UE at specific post-connection states (registration/authentication/RRC) without standing up a full rogue base station — used for modem crashes, downgrades, fingerprinting and auth-bypass research. The lighter-footprint active option when you don’t want to run a full rogue cell.", "deps": ["usrp-b210"], "needs": "A USRP B210/X310 and a strong host (12-core/16 GB, Ubuntu 22.04); FR1/sub-6. Injects into a live link — authorised testing only.", "caveat": "Research framework; transmits crafted frames at a target — authorised lab use only." }, - { "tool": "5greplay", "role": "NGAP/NAS replay & fuzzing", "why": "Replays and mutates captured 5G control-plane traffic against your own core — feed it a capture, write rules to alter NGAP/NAS-5GS fields, and fire the modified packets at an AMF/SMF (or a gNB) to fuzz the procedure handling. Tests the core/RAN over the network rather than over the air, so no SDR.", "deps": ["wireshark"], "needs": "A capture of 5G control-plane traffic (e.g. from the Capture step, saved out of Wireshark) and a target 5G component you are authorised to test (your own Open5GS/free5GC AMF/SMF or test gNB).", "caveat": "Sends mutated signalling at a live target component — authorised testing of your own core only." }, - { "tool": "open5gs", "role": "5G core behind the test cell", "why": "Provides the AMF/SMF/UPF/AUSF/UDM the gNB needs to run registration, 5G-AKA authentication and NAS-5GS procedures end-to-end — so you control subscriber data, steer the identity exchange, and absorb registration/RRC floods while you measure the core’s behaviour. Open5GS supports both EPC and 5GC.", "deps": [], "needs": "Pure host software with no radio of its own — runs on the host behind the srsRAN/OAI rogue gNB above (the SDR belongs to the gNB); configure your test PLMN and test-SIM credentials. Authorised testing only." }, - { "tool": "free5gc", "role": "Alternative 5G core", "why": "A second, independent 5G core (3GPP R15) you control — use it to cross-check core behaviour against Open5GS, or when a tool/UE expects free5GC’s configuration. Provision test subscribers in its UDM/UDR and drive the same registration/auth/NAS-5GS procedures behind your test gNB.", "deps": [], "needs": "Pure host software with no radio of its own — runs on the host behind the srsRAN/OAI gNB (the SDR belongs to the gNB); configure your test PLMN and test-SIM credentials. SA only. Authorised testing only." } + { "tool": "srsran-project", "role": "Rogue / test gNB", "why": "Stands up a full 5G NR gNB (CU/DU) on an SDR, your own PCI, PLMN and SIBs on a test NR-ARFCN, so a test UE camps and you can drive the registration/identity exchange, attempt downgrade, or flood RRC/NAS signalling. The reference open platform for fake-gNB and 5G rogue-cell research.", "deps": ["usrp-b210", "bladerf-2-micro", "signalsdr-pro"], "needs": "A full-duplex TX-capable SDR (B210/bladeRF/SignalSDR), a test UE with a known/programmable 5G SIM, and a 5G core (Open5GS or free5GC) behind it. FR1/sub-6. Authorised, RF-contained testing only.", "caveat": "The srsRAN_Project (5G) GitHub repo is archived, check srsran.com for current builds. Transmits in licensed spectrum, authorised lab/shielded use only." }, + { "tool": "openairinterface5g", "role": "Alternative rogue gNB / RRC-NAS fuzzing", "why": "A second, independent full 5G RAN+core stack: stand up the test/rogue gNB on OAI when you want a different implementation to cross-check, or to drive RRC/NAS signalling and protocol fuzzing that the srsRAN path doesn’t expose as cleanly. It is also the gNB platform that 5Ghoul builds on.", "deps": ["usrp-b210", "bladerf-2-micro", "signalsdr-pro"], "needs": "A TX-capable SDR and a test UE; OAI runs its own 5G core or pairs with Open5GS/free5GC. FR1/sub-6. Authorised, RF-contained testing only.", "caveat": "Heavier build/tuning than srsRAN; transmits in licensed spectrum, authorised lab use only." }, + { "tool": "5ghoul", "role": "Baseband attack / fuzzing (worked example)", "why": "A ready-made set of pre-authentication 5G NR RRC/NAS vulnerabilities plus a fuzzer that drives a malicious OAI gNB to crash or disrupt COTS Qualcomm/MediaTek smartphone basebands, a concrete, turnkey instance of the rogue-gNB baseband-attack surface rather than rolling it from the base stack.", "deps": ["usrp-b210", "bladerf-2-micro", "signalsdr-pro"], "needs": "Runs on an OpenAirInterface gNB with a TX-capable SDR and a target UE; FR1/sub-6. Authorised, RF-contained testing of your own device only.", "caveat": "Built on OAI; disrupts real basebands, authorised lab/shielded use only." }, + { "tool": "sni5gect", "role": "MAC-NR downlink injection", "why": "Injects crafted MAC-NR downlink packets to a target UE at specific post-connection states (registration/authentication/RRC) without standing up a full rogue base station, used for modem crashes, downgrades, fingerprinting and auth-bypass research. The lighter-footprint active option when you don’t want to run a full rogue cell.", "deps": ["usrp-b210"], "needs": "A USRP B210/X310 and a strong host (12-core/16 GB, Ubuntu 22.04); FR1/sub-6. Injects into a live link, authorised testing only.", "caveat": "Research framework; transmits crafted frames at a target, authorised lab use only." }, + { "tool": "5greplay", "role": "NGAP/NAS replay & fuzzing", "why": "Replays and mutates captured 5G control-plane traffic against your own core, feed it a capture, write rules to alter NGAP/NAS-5GS fields, and fire the modified packets at an AMF/SMF (or a gNB) to fuzz the procedure handling. Tests the core/RAN over the network rather than over the air, so no SDR.", "deps": ["wireshark"], "needs": "A capture of 5G control-plane traffic (e.g. from the Capture step, saved out of Wireshark) and a target 5G component you are authorised to test (your own Open5GS/free5GC AMF/SMF or test gNB).", "caveat": "Sends mutated signalling at a live target component, authorised testing of your own core only." }, + { "tool": "open5gs", "role": "5G core behind the test cell", "why": "Provides the AMF/SMF/UPF/AUSF/UDM the gNB needs to run registration, 5G-AKA authentication and NAS-5GS procedures end-to-end, so you control subscriber data, steer the identity exchange, and absorb registration/RRC floods while you measure the core’s behaviour. Open5GS supports both EPC and 5GC.", "deps": [], "needs": "Pure host software with no radio of its own, runs on the host behind the srsRAN/OAI rogue gNB above (the SDR belongs to the gNB); configure your test PLMN and test-SIM credentials. Authorised testing only." }, + { "tool": "free5gc", "role": "Alternative 5G core", "why": "A second, independent 5G core (3GPP R15) you control, use it to cross-check core behaviour against Open5GS, or when a tool/UE expects free5GC’s configuration. Provision test subscribers in its UDM/UDR and drive the same registration/auth/NAS-5GS procedures behind your test gNB.", "deps": [], "needs": "Pure host software with no radio of its own, runs on the host behind the srsRAN/OAI gNB (the SDR belongs to the gNB); configure your test PLMN and test-SIM credentials. SA only. Authorised testing only." } ] }, "AP": { - "note": "Above the air link, 5G’s ‘application layer’ is the NAS-5GS / 5G-core signalling — registration, 5G-AKA authentication, identity (SUCI/5G-GUTI) and PDU-session procedures between the UE and the core, carried over NGAP between the gNB and the AMF. You can only exercise these by being the network: with your own gNB + 5G core (the Attack step) and an authorised test UE, drive and inspect the NAS-5GS exchange — watch the SUCI/SUPI and 5G-GUTI handling, force re-authentication or identity requests, and test how the device behaves under hostile core signalling. This is end-to-end control-plane testing of the device-to-network trust, done on equipment you own and are authorised to operate.", + "note": "Above the air link, 5G’s ‘application layer’ is the NAS-5GS / 5G-core signalling, registration, 5G-AKA authentication, identity (SUCI/5G-GUTI) and PDU-session procedures between the UE and the core, carried over NGAP between the gNB and the AMF. You can only exercise these by being the network: with your own gNB + 5G core (the Attack step) and an authorised test UE, drive and inspect the NAS-5GS exchange, watch the SUCI/SUPI and 5G-GUTI handling, force re-authentication or identity requests, and test how the device behaves under hostile core signalling. This is end-to-end control-plane testing of the device-to-network trust, done on equipment you own and are authorised to operate.", "tools": [ - { "tool": "open5gs", "role": "5GC / NAS-5GS test harness", "why": "A full 5G core (AMF/SMF/UPF/AUSF/UDM) you control: provision test subscribers and drive the registration/5G-AKA/identity and PDU-session NAS-5GS procedures to probe how a UE handles the control plane — the platform for app-/control-layer 5G testing once your own cell is up.", "deps": [], "needs": "Host software with no radio of its own — pairs with the srsRAN/OAI test gNB (which supplies the TX-capable SDR); configure your test PLMN and test-SIM credentials. Authorised testing only.", "caveat": "Requires running your own radiating gNB — authorised, RF-contained use only." }, - { "tool": "free5gc", "role": "Alternative 5GC / NAS-5GS harness", "why": "An independent 5G core for the same control-plane testing — provision subscribers in its UDM and drive registration/auth/NAS-5GS procedures, useful to cross-check a UE’s behaviour against a second core implementation.", "deps": [], "needs": "Host software with no radio of its own — pairs with the srsRAN/OAI test gNB (which supplies the TX-capable SDR); SA only. Configure your test PLMN and test-SIM credentials. Authorised testing only.", "caveat": "Requires running your own radiating gNB — authorised, RF-contained use only." }, - { "tool": "5greplay", "role": "NAS/NGAP procedure fuzzing", "why": "Replays and mutates captured NAS-5GS/NGAP procedures against your own AMF/SMF to test how the core handles malformed or out-of-sequence control-plane messages — application-layer fuzzing of the 5G core over the network, no radio.", "deps": ["wireshark"], "needs": "A capture of 5G control-plane traffic (saved from Wireshark) and your own 5G core (Open5GS/free5GC) as the target. Authorised testing of your own core only." } + { "tool": "open5gs", "role": "5GC / NAS-5GS test harness", "why": "A full 5G core (AMF/SMF/UPF/AUSF/UDM) you control: provision test subscribers and drive the registration/5G-AKA/identity and PDU-session NAS-5GS procedures to probe how a UE handles the control plane, the platform for app-/control-layer 5G testing once your own cell is up.", "deps": [], "needs": "Host software with no radio of its own, pairs with the srsRAN/OAI test gNB (which supplies the TX-capable SDR); configure your test PLMN and test-SIM credentials. Authorised testing only.", "caveat": "Requires running your own radiating gNB, authorised, RF-contained use only." }, + { "tool": "free5gc", "role": "Alternative 5GC / NAS-5GS harness", "why": "An independent 5G core for the same control-plane testing, provision subscribers in its UDM and drive registration/auth/NAS-5GS procedures, useful to cross-check a UE’s behaviour against a second core implementation.", "deps": [], "needs": "Host software with no radio of its own, pairs with the srsRAN/OAI test gNB (which supplies the TX-capable SDR); SA only. Configure your test PLMN and test-SIM credentials. Authorised testing only.", "caveat": "Requires running your own radiating gNB, authorised, RF-contained use only." }, + { "tool": "5greplay", "role": "NAS/NGAP procedure fuzzing", "why": "Replays and mutates captured NAS-5GS/NGAP procedures against your own AMF/SMF to test how the core handles malformed or out-of-sequence control-plane messages, application-layer fuzzing of the 5G core over the network, no radio.", "deps": ["wireshark"], "needs": "A capture of 5G control-plane traffic (saved from Wireshark) and your own 5G core (Open5GS/free5GC) as the target. Authorised testing of your own core only." } ] } } diff --git a/src/data/toolchains/rfid.js b/src/data/toolchains/rfid.js index 410490c..efd655c 100644 --- a/src/data/toolchains/rfid.js +++ b/src/data/toolchains/rfid.js @@ -1,9 +1,9 @@ export default { "status": "complete", "facts": [ - { "k": "Bands", "v": "LF 125 / 134 kHz · HF 13.56 MHz — near-field (magnetically coupled), no far-field radiation to survey" }, - { "k": "LF standards", "v": "EM4100/EM4102, HID Prox (125 kHz), Indala, T5577 (writable clone chip), HITAG — mostly read-only IDs with little or no crypto" }, - { "k": "HF standards", "v": "ISO 14443-A/B (MIFARE Classic, Ultralight, NTAG, DESFire, contactless EMV), ISO 15693 (iCODE/vicinity), FeliCa — 13.56 MHz" }, + { "k": "Bands", "v": "LF 125 / 134 kHz · HF 13.56 MHz, near-field (magnetically coupled), no far-field radiation to survey" }, + { "k": "LF standards", "v": "EM4100/EM4102, HID Prox (125 kHz), Indala, T5577 (writable clone chip), HITAG, mostly read-only IDs with little or no crypto" }, + { "k": "HF standards", "v": "ISO 14443-A/B (MIFARE Classic, Ultralight, NTAG, DESFire, contactless EMV), ISO 15693 (iCODE/vicinity), FeliCa, 13.56 MHz" }, { "k": "Crypto", "v": "MIFARE Classic uses Crypto1 (48-bit, broken: darkside/nested/hardnested, mfkey32). DESFire EV1/2/3 (AES/3DES) and modern NTAG/ICODE are not Crypto1-breakable." }, { "k": "Range", "v": "Centimetres by design (a few cm typical, up to ~10 cm for HF; LF even shorter). Long-range reads need oversized antennas or a relay." } ], @@ -12,55 +12,55 @@ export default { "IG": { "note": "Work out what the credential is before touching crypto. The first fork is the carrier frequency: a 125 kHz LF tag (EM4100, HID Prox) is a different world from a 13.56 MHz HF card (MIFARE, DESFire, NTAG). LF tags are usually fixed read-only IDs with no real security; HF cards range from trivially cloneable (MIFARE Classic) to genuinely strong (DESFire EV2 with AES). Identify the frequency, the standard, the chip family and the security mode, and you already know which steps below even apply.", "lookFor": [ - "Carrier frequency — LF 125/134 kHz vs HF 13.56 MHz. Decides every tool choice and is often printed on the reader or readable with a Proxmark autodetect.", - "Standard / chip family — EM4100, HID Prox, Indala, HITAG (LF); ISO 14443-A/B MIFARE Classic, Ultralight, NTAG, DESFire, contactless EMV; ISO 15693 / FeliCa (HF). Cross-reference known issues (Crypto1 break, MIFARE Classic nested/hardnested, default keys).", - "UID and whether it is fixed or changeable — 4-byte vs 7-byte; ‘magic’ Gen1a/Gen2 Chinese cards allow writing block 0 (the UID) for a full clone.", - "For MIFARE Classic: which sectors are in use, and whether they still hold default/transport keys (FFFFFFFFFFFF, A0A1A2…, etc.) — a default key skips the whole crypto step.", - "Security mode — open/read-only ID vs Crypto1-protected (MIFARE Classic) vs strong crypto (DESFire AES, modern NTAG with password/SUN). The latter resists the attacks below by design.", - "Application data on the card — access-control facility/card number (HID Prox 26-bit Wiegand etc.), value blocks on transit/payment cards, NDEF records on NTAG." + "Carrier frequency, LF 125/134 kHz vs HF 13.56 MHz. Decides every tool choice and is often printed on the reader or readable with a Proxmark autodetect.", + "Standard / chip family, EM4100, HID Prox, Indala, HITAG (LF); ISO 14443-A/B MIFARE Classic, Ultralight, NTAG, DESFire, contactless EMV; ISO 15693 / FeliCa (HF). Cross-reference known issues (Crypto1 break, MIFARE Classic nested/hardnested, default keys).", + "UID and whether it is fixed or changeable, 4-byte vs 7-byte; ‘magic’ Gen1a/Gen2 Chinese cards allow writing block 0 (the UID) for a full clone.", + "For MIFARE Classic: which sectors are in use, and whether they still hold default/transport keys (FFFFFFFFFFFF, A0A1A2…, etc.), a default key skips the whole crypto step.", + "Security mode, open/read-only ID vs Crypto1-protected (MIFARE Classic) vs strong crypto (DESFire AES, modern NTAG with password/SUN). The latter resists the attacks below by design.", + "Application data on the card, access-control facility/card number (HID Prox 26-bit Wiegand etc.), value blocks on transit/payment cards, NDEF records on NTAG." ] }, "SP": { - "note": "There is no far-field spectrum to survey: LF and HF are near-field, so ‘see it’ means powering the tag in the field and reading back its carrier, standard and chip. The reader IS the instrument here — a single command interrogates the card and tells you the frequency band, the modulation/standard and often the exact chip. Run the LF autodetect for 125 kHz tags and the HF autodetect for 13.56 MHz cards from the Proxmark client; the Chameleon (driven from its GUI app) can do the same field read when that is the hardware you have. There is also a passive path: when a legitimate reader and card are already transacting, the Proxmark can sniff that exchange (`hf 14a sniff`, `hf 15 sniff`, `lf sniff`) without transmitting — it adds no field of its own, only listening to the reader's carrier and the card's load modulation — so you read the standard, the UID and the live command traffic without energising anything yourself.", + "note": "There is no far-field spectrum to survey: LF and HF are near-field, so ‘see it’ means powering the tag in the field and reading back its carrier, standard and chip. The reader IS the instrument here, a single command interrogates the card and tells you the frequency band, the modulation/standard and often the exact chip. Run the LF autodetect for 125 kHz tags and the HF autodetect for 13.56 MHz cards from the Proxmark client; the Chameleon (driven from its GUI app) can do the same field read when that is the hardware you have. There is also a passive path: when a legitimate reader and card are already transacting, the Proxmark can sniff that exchange (`hf 14a sniff`, `hf 15 sniff`, `lf sniff`) without transmitting, it adds no field of its own, only listening to the reader's carrier and the card's load modulation, so you read the standard, the UID and the live command traffic without energising anything yourself.", "tools": [ - { "tool": "pm3-client", "role": "Carrier / standard / chip ID", "why": "The `pm3` client's `lf search` and `hf search` energise the field through the Proxmark and fingerprint the tag — band, standard (EM4100, HID, ISO 14443-A, ISO 15693…) and chip type — in one command. The reference identification step for both bands.", "deps": ["proxmark3"] }, - { "tool": "pm3-client", "role": "Passive sniffer", "why": "When a real reader and card are already interacting, `hf 14a sniff` / `hf 15 sniff` / `lf sniff` eavesdrop the exchange through the Proxmark without transmitting — the reader supplies the field and the Proxmark only records both sides — so you see the standard, the UID and the actual command/APDU traffic from a genuine transaction. The reader↔card authentication it captures is also what mfkey32/mfkey64 need at the Break-crypto step.", "deps": ["proxmark3"] }, + { "tool": "pm3-client", "role": "Carrier / standard / chip ID", "why": "The `pm3` client's `lf search` and `hf search` energise the field through the Proxmark and fingerprint the tag, band, standard (EM4100, HID, ISO 14443-A, ISO 15693…) and chip type, in one command. The reference identification step for both bands.", "deps": ["proxmark3"] }, + { "tool": "pm3-client", "role": "Passive sniffer", "why": "When a real reader and card are already interacting, `hf 14a sniff` / `hf 15 sniff` / `lf sniff` eavesdrop the exchange through the Proxmark without transmitting, the reader supplies the field and the Proxmark only records both sides, so you see the standard, the UID and the actual command/APDU traffic from a genuine transaction. The reader↔card authentication it captures is also what mfkey32/mfkey64 need at the Break-crypto step.", "deps": ["proxmark3"] }, { "tool": "chameleon-ultra-gui", "role": "Field read / ID", "why": "The Chameleon Ultra GUI app reads and fingerprints LF and HF tags from a pocket device when you don’t have a Proxmark to hand.", "caveat": "Card emulator first; its read/ID coverage is narrower than the Proxmark’s.", "deps": ["chameleon-ultra"] } ] }, "PHY": { - "note": "No standalone RFID demodulator in this kit and none needed: the reader’s analog front-end demodulates the load-modulated carrier and frames the bytes in hardware, so capture and demodulation are one step on the device itself. The client tools below pull the framed data off the reader — there is no separate I/Q or PHY stage to drive." + "note": "No standalone RFID demodulator in this kit and none needed: the reader’s analog front-end demodulates the load-modulated carrier and frames the bytes in hardware, so capture and demodulation are one step on the device itself. The client tools below pull the framed data off the reader, there is no separate I/Q or PHY stage to drive." }, "LL": { - "note": "Read or dump the tag’s data off the reader. For an LF ID this is the raw card number; for an HF card it is the per-sector/per-block contents (as far as the keys you hold allow). Pick the device you have: the Proxmark (driven from the pm3 client) reads and dumps both bands and is the most capable; libnfc drives a cheap USB PN532/ACR122U reader for HF MIFARE work; the Chameleon (via its GUI app) and BomberCat read HF cards standalone. There is no PCAP and no Wireshark here — the reader’s own client is the decoder.", + "note": "Read or dump the tag’s data off the reader. For an LF ID this is the raw card number; for an HF card it is the per-sector/per-block contents (as far as the keys you hold allow). Pick the device you have: the Proxmark (driven from the pm3 client) reads and dumps both bands and is the most capable; libnfc drives a cheap USB PN532/ACR122U reader for HF MIFARE work; the Chameleon (via its GUI app) and BomberCat read HF cards standalone. There is no PCAP and no Wireshark here, the reader’s own client is the decoder.", "tools": [ { "tool": "pm3-client", "role": "Primary reader / dumper", "why": "The `pm3` client reads and dumps LF IDs and HF cards across the widest range of standards through the Proxmark, and writes the dump to a file you carry into the crypto and attack steps. The default capture device.", "deps": ["proxmark3"] }, - { "tool": "libnfc", "role": "HF reader stack", "why": "The host library that drives a cheap PN532/ACR122U USB reader (`nfc-list`, `nfc-mfclassic`) to read and dump ISO 14443-A MIFARE cards without a Proxmark — and the engine the mfoc/mfcuk crackers run on.", "deps": ["acr122u"] }, - { "tool": "chameleon-ultra-gui", "role": "Pocket reader", "why": "The Chameleon Ultra GUI reads HF (and LF) cards standalone and stores them as slots, ready to replay/emulate at the attack step — capture and impersonation on one device.", "deps": ["chameleon-ultra"] }, + { "tool": "libnfc", "role": "HF reader stack", "why": "The host library that drives a cheap PN532/ACR122U USB reader (`nfc-list`, `nfc-mfclassic`) to read and dump ISO 14443-A MIFARE cards without a Proxmark, and the engine the mfoc/mfcuk crackers run on.", "deps": ["acr122u"] }, + { "tool": "chameleon-ultra-gui", "role": "Pocket reader", "why": "The Chameleon Ultra GUI reads HF (and LF) cards standalone and stores them as slots, ready to replay/emulate at the attack step, capture and impersonation on one device.", "deps": ["chameleon-ultra"] }, { "tool": "bombercat", "role": "NFC read / relay capture", "why": "PN7150-based reader for HF/NFC read and emulate, and the capture end of an NFC relay (RelayNFC) between a real card and a reader.", "deps": [] } ] }, "CR": { - "note": "This step is almost entirely MIFARE Classic. Its Crypto1 cipher is broken, so a card with non-default keys still falls: if you hold one known key for any sector, the ‘nested’ attack recovers the rest; with no known key, the ‘darkside’ attack bootstraps the first one; ‘hardnested’ handles hardened/EV1 Classic that resists plain nested; and mfkey32/mfkey64 recover a key from a sniffed reader↔card authentication. LF IDs need no cracking, and DESFire/modern NTAG (AES/3DES) are out of scope for these attacks — recognise them and stop.", + "note": "This step is almost entirely MIFARE Classic. Its Crypto1 cipher is broken, so a card with non-default keys still falls: if you hold one known key for any sector, the ‘nested’ attack recovers the rest; with no known key, the ‘darkside’ attack bootstraps the first one; ‘hardnested’ handles hardened/EV1 Classic that resists plain nested; and mfkey32/mfkey64 recover a key from a sniffed reader↔card authentication. LF IDs need no cracking, and DESFire/modern NTAG (AES/3DES) are out of scope for these attacks, recognise them and stop.", "tools": [ - { "tool": "pm3-client", "role": "Full Crypto1 suite", "why": "The Iceman `pm3` client carries the complete toolkit driving one Proxmark: `hf mf darkside`, `nested`, `hardnested`, and `mfkey32`/`mfkey64` to recover a key from a sniffed reader transaction — then dumps the now-readable sectors.", "deps": ["proxmark3"], "needs": "Runs live against the card in the field (or against a reader→card transaction it sniffed). No external dump needed — it cracks and then reads the card itself." }, - { "tool": "mfoc", "role": "Nested attack (known key)", "why": "Offline MIFARE Classic cracker: given at least one known/default sector key it runs the nested attack to recover all remaining keys and dumps the card, on a cheap PN532 reader.", "deps": ["libnfc", "acr122u"], "needs": "A MIFARE Classic card present on a libnfc-driven PN532/ACR122U reader (from the Capture step), plus at least one known key — default/transport keys are tried automatically." }, - { "tool": "mfcuk", "role": "Darkside attack (no key)", "why": "Implements the darkside attack to recover a first sector key when none of the default keys work — the bootstrap that lets mfoc finish the rest.", "deps": ["libnfc", "acr122u"], "needs": "A MIFARE Classic card on a libnfc-driven PN532/ACR122U reader with no usable known key; pass the recovered key to mfoc (or the Proxmark) to dump the rest." } + { "tool": "pm3-client", "role": "Full Crypto1 suite", "why": "The Iceman `pm3` client carries the complete toolkit driving one Proxmark: `hf mf darkside`, `nested`, `hardnested`, and `mfkey32`/`mfkey64` to recover a key from a sniffed reader transaction, then dumps the now-readable sectors.", "deps": ["proxmark3"], "needs": "Runs live against the card in the field (or against a reader→card transaction it sniffed). No external dump needed, it cracks and then reads the card itself." }, + { "tool": "mfoc", "role": "Nested attack (known key)", "why": "Offline MIFARE Classic cracker: given at least one known/default sector key it runs the nested attack to recover all remaining keys and dumps the card, on a cheap PN532 reader.", "deps": ["libnfc", "acr122u"], "needs": "A MIFARE Classic card present on a libnfc-driven PN532/ACR122U reader (from the Capture step), plus at least one known key, default/transport keys are tried automatically." }, + { "tool": "mfcuk", "role": "Darkside attack (no key)", "why": "Implements the darkside attack to recover a first sector key when none of the default keys work, the bootstrap that lets mfoc finish the rest.", "deps": ["libnfc", "acr122u"], "needs": "A MIFARE Classic card on a libnfc-driven PN532/ACR122U reader with no usable known key; pass the recovered key to mfoc (or the Proxmark) to dump the rest." } ] }, "AT": { - "note": "With the data and keys in hand, take over: clone the credential to a blank, emulate it from a programmable device, or relay a live card to a reader at distance. LF EM/HID IDs clone straight onto a T5577. HF MIFARE Classic dumps write onto a ‘magic’ Gen1a/Gen2 card (UID and all) or are emulated. A relay/MITM defeats the proximity assumption entirely — sit between the card and the reader, or relay a card the reader believes is right in front of it, without needing the card’s keys.", + "note": "With the data and keys in hand, take over: clone the credential to a blank, emulate it from a programmable device, or relay a live card to a reader at distance. LF EM/HID IDs clone straight onto a T5577. HF MIFARE Classic dumps write onto a ‘magic’ Gen1a/Gen2 card (UID and all) or are emulated. A relay/MITM defeats the proximity assumption entirely, sit between the card and the reader, or relay a card the reader believes is right in front of it, without needing the card’s keys.", "tools": [ { "tool": "pm3-client", "role": "Clone / write / simulate", "why": "The `pm3` client writes a recovered LF ID to a T5577 or an HF dump to a magic card for a physical clone, and can simulate a tag (`hf mf sim` / `lf … sim`) straight from the Proxmark.", "deps": ["proxmark3"], "needs": "The dump/keys from the Capture and Crypto steps, plus a writable blank (T5577 for LF, magic Gen1a/Gen2 for HF MIFARE Classic) for a physical clone." }, - { "tool": "pm3-client", "role": "NFC relay / MITM", "why": "Drives an ISO 14443-A relay/MITM through the Proxmark: `hf 14a sniff` eavesdrops the reader↔card exchange, and the `hf_reblay` standalone firmware mode relays a live card to a target reader (or sits between card and reader) — an attack that needs no keys at all. Two Proxmarks (mole + proxy) for a full end-to-end relay.", "deps": ["proxmark3"], "needs": "A live card and a target reader; for a full long-distance relay, a second Proxmark/host at the card end. No dump or recovered key required." }, - { "tool": "chameleon-ultra-gui", "role": "Emulate / impersonate", "why": "The Chameleon Ultra GUI emulates a full MIFARE Classic (Crypto1) and other HF/LF tags from stored slots — present the cloned credential to a reader with no blank card at all.", "deps": ["chameleon-ultra"], "needs": "A card dump loaded into a slot (read at the Capture step or cracked at the Crypto step)." }, - { "tool": "bombercat", "role": "Relay / MITM / MagSpoof", "why": "Relays an NFC transaction between a distant real card and a target reader (RelayNFC) — a card-present MITM that needs no keys — and replays magnetic-stripe tracks to legacy readers (MagSpoof).", "deps": [] } + { "tool": "pm3-client", "role": "NFC relay / MITM", "why": "Drives an ISO 14443-A relay/MITM through the Proxmark: `hf 14a sniff` eavesdrops the reader↔card exchange, and the `hf_reblay` standalone firmware mode relays a live card to a target reader (or sits between card and reader), an attack that needs no keys at all. Two Proxmarks (mole + proxy) for a full end-to-end relay.", "deps": ["proxmark3"], "needs": "A live card and a target reader; for a full long-distance relay, a second Proxmark/host at the card end. No dump or recovered key required." }, + { "tool": "chameleon-ultra-gui", "role": "Emulate / impersonate", "why": "The Chameleon Ultra GUI emulates a full MIFARE Classic (Crypto1) and other HF/LF tags from stored slots, present the cloned credential to a reader with no blank card at all.", "deps": ["chameleon-ultra"], "needs": "A card dump loaded into a slot (read at the Capture step or cracked at the Crypto step)." }, + { "tool": "bombercat", "role": "Relay / MITM / MagSpoof", "why": "Relays an NFC transaction between a distant real card and a target reader (RelayNFC), a card-present MITM that needs no keys, and replays magnetic-stripe tracks to legacy readers (MagSpoof).", "deps": [] } ] }, "AP": { - "note": "Above the bytes sits the application: the access-control facility/card number, transit value blocks, EMV records or NDEF data the dump actually encodes. Mostly this is reading meaning out of a recovered dump — the Proxmark client decodes many formats inline, and a dump parser turns a raw MIFARE Classic dump into human-readable sectors, keys and access bits so you can see and tamper with what the card asserts.", + "note": "Above the bytes sits the application: the access-control facility/card number, transit value blocks, EMV records or NDEF data the dump actually encodes. Mostly this is reading meaning out of a recovered dump, the Proxmark client decodes many formats inline, and a dump parser turns a raw MIFARE Classic dump into human-readable sectors, keys and access bits so you can see and tamper with what the card asserts.", "tools": [ - { "tool": "mfdread", "role": "Dump parser", "why": "Renders a MIFARE Classic 1k/4k dump in human-readable form — per-sector data, keys A/B and the access-condition bits — so you can read off the application data and spot writable/value blocks.", "deps": ["pm3-client"], "needs": "A .mfd/.bin/.eml dump produced at the Capture/Crypto step by the Proxmark (or mfoc) — feed that file to mfdread." } + { "tool": "mfdread", "role": "Dump parser", "why": "Renders a MIFARE Classic 1k/4k dump in human-readable form, per-sector data, keys A/B and the access-condition bits, so you can read off the application data and spot writable/value blocks.", "deps": ["pm3-client"], "needs": "A .mfd/.bin/.eml dump produced at the Capture/Crypto step by the Proxmark (or mfoc), feed that file to mfdread." } ] } } diff --git a/src/data/toolchains/subg.js b/src/data/toolchains/subg.js index eafb2fd..4bc4818 100644 --- a/src/data/toolchains/subg.js +++ b/src/data/toolchains/subg.js @@ -1,63 +1,63 @@ export default { "status": "complete", "facts": [ - { "k": "Bands", "v": "Unlicensed sub-GHz ISM, regional: 315 MHz (North America/Asia remotes & TPMS) · 433.92 MHz (the global workhorse — remotes, sensors, alarms) · 868 MHz (EU — wM-Bus meters, smart-home) · 915 MHz (US ISM, 902–928)" }, - { "k": "Modulation", "v": "Almost everything is OOK/ASK (on-off keying — the carrier blinks the bits, cheapest to build) or (G)FSK (the carrier shifts between two frequencies). A handful use minor variants; there is no spread spectrum here, so the signals are simple to demodulate once you know the baud rate." }, - { "k": "Encoding / baud", "v": "Bits are usually PWM/Manchester/PPM at a few hundred to a few thousand baud, in short repeated bursts. A frame is typically an ID + a few state/sensor bytes + a checksum — small, and often repeated several times per press for reliability." }, - { "k": "Code type", "v": "Fixed-code (the same payload every time — trivially captured and replayed) vs rolling-code / hopping (each press sends a new value from a counter, e.g. KeeLoq, HCS301): a naive replay of an old rolling code is rejected by the receiver." }, - { "k": "Crypto", "v": "Most sub-GHz devices have NO confidentiality — fixed-code remotes and sensors send their payload in the clear. Rolling codes add replay resistance, not encryption you decrypt from a capture; KeeLoq's block cipher needs the manufacturer key to forge a valid next code, which a passive capture does not yield." }, + { "k": "Bands", "v": "Unlicensed sub-GHz ISM, regional: 315 MHz (North America/Asia remotes & TPMS) · 433.92 MHz (the global workhorse, remotes, sensors, alarms) · 868 MHz (EU, wM-Bus meters, smart-home) · 915 MHz (US ISM, 902 to 928)" }, + { "k": "Modulation", "v": "Almost everything is OOK/ASK (on-off keying, the carrier blinks the bits, cheapest to build) or (G)FSK (the carrier shifts between two frequencies). A handful use minor variants; there is no spread spectrum here, so the signals are simple to demodulate once you know the baud rate." }, + { "k": "Encoding / baud", "v": "Bits are usually PWM/Manchester/PPM at a few hundred to a few thousand baud, in short repeated bursts. A frame is typically an ID + a few state/sensor bytes + a checksum, small, and often repeated several times per press for reliability." }, + { "k": "Code type", "v": "Fixed-code (the same payload every time, trivially captured and replayed) vs rolling-code / hopping (each press sends a new value from a counter, e.g. KeeLoq, HCS301): a naive replay of an old rolling code is rejected by the receiver." }, + { "k": "Crypto", "v": "Most sub-GHz devices have NO confidentiality, fixed-code remotes and sensors send their payload in the clear. Rolling codes add replay resistance, not encryption you decrypt from a capture; KeeLoq's block cipher needs the manufacturer key to forge a valid next code, which a passive capture does not yield." }, { "k": "Targets", "v": "Garage/gate remotes & car key fobs, TPMS sensors, wireless weather/soil/temperature stations, 433 MHz smart-home plugs and doorbells, wM-Bus smart meters, and alarm door/window contacts." } ], "reference": null, "layers": { "IG": { - "note": "Work out what the device is before any RF work — no capture yet. Sub-GHz is a grab-bag of cheap one-way gadgets, so the first job is to pin down four things: which frequency it transmits on, whether it is OOK/ASK or FSK, roughly how fast it sends, and — the question that decides everything downstream — whether it is a fixed code (the same payload every time, replayable) or a rolling/hopping code (a new value each press, e.g. KeeLoq). Much of this comes off the device itself: the FCC ID printed on the label looks up the exact frequency, modulation and a test report on fccid.io, and a teardown reveals the radio chip (a CC1101, a PT2262/EV1527 OOK encoder, an HCS301/KeeLoq rolling-code chip…).", + "note": "Work out what the device is before any RF work, no capture yet. Sub-GHz is a grab-bag of cheap one-way gadgets, so the first job is to pin down four things: which frequency it transmits on, whether it is OOK/ASK or FSK, roughly how fast it sends, and, the question that decides everything downstream, whether it is a fixed code (the same payload every time, replayable) or a rolling/hopping code (a new value each press, e.g. KeeLoq). Much of this comes off the device itself: the FCC ID printed on the label looks up the exact frequency, modulation and a test report on fccid.io, and a teardown reveals the radio chip (a CC1101, a PT2262/EV1527 OOK encoder, an HCS301/KeeLoq rolling-code chip…).", "lookFor": [ - "Carrier frequency — 315 / 433.92 / 868 / 915 MHz. The FCC ID on the label resolves the exact frequency and band (fccid.io); a quick gqrx sweep of the ISM bands confirms it. This sets every radio and tool choice below.", - "Modulation — OOK/ASK (the carrier blinks on and off — by far the most common) vs (G)FSK (the carrier shifts between two tones). Visible on a waterfall and reported by rtl_433/URH; it sets the demodulator settings.", - "Encoding and baud rate — PWM / Manchester / PPM at a few hundred to a few thousand baud, sent as short repeated bursts. URH auto-estimates it; you need it to turn the burst into bits.", - "Fixed vs rolling code — does the same press always send the same payload (fixed: PT2262/EV1527-class, replayable) or a different value each time (rolling/hopping: KeeLoq/HCS301)? This single fact decides whether a plain capture-and-replay works or you need a RollJam-style attack.", - "Radio chip and encoder (FCC ID, teardown) — CC1101 transceiver, a fixed-code OOK encoder (PT2262/EV1527/HT12), or a rolling-code chip (HCS200/300/301 KeeLoq). The chip tells you the protocol family and which rtl_433 decoder or known attack applies.", - "Device class and what the payload means — remote/fob, TPMS, weather/soil sensor, smart-home switch, wM-Bus meter, alarm contact. rtl_433's named decoders already cover hundreds of these, so identifying the class often hands you the field layout for free." + "Carrier frequency, 315 / 433.92 / 868 / 915 MHz. The FCC ID on the label resolves the exact frequency and band (fccid.io); a quick gqrx sweep of the ISM bands confirms it. This sets every radio and tool choice below.", + "Modulation, OOK/ASK (the carrier blinks on and off, by far the most common) vs (G)FSK (the carrier shifts between two tones). Visible on a waterfall and reported by rtl_433/URH; it sets the demodulator settings.", + "Encoding and baud rate, PWM / Manchester / PPM at a few hundred to a few thousand baud, sent as short repeated bursts. URH auto-estimates it; you need it to turn the burst into bits.", + "Fixed vs rolling code, does the same press always send the same payload (fixed: PT2262/EV1527-class, replayable) or a different value each time (rolling/hopping: KeeLoq/HCS301)? This single fact decides whether a plain capture-and-replay works or you need a RollJam-style attack.", + "Radio chip and encoder (FCC ID, teardown), CC1101 transceiver, a fixed-code OOK encoder (PT2262/EV1527/HT12), or a rolling-code chip (HCS200/300/301 KeeLoq). The chip tells you the protocol family and which rtl_433 decoder or known attack applies.", + "Device class and what the payload means, remote/fob, TPMS, weather/soil sensor, smart-home switch, wM-Bus meter, alarm contact. rtl_433's named decoders already cover hundreds of these, so identifying the class often hands you the field layout for free." ] }, "SP": { - "note": "Find where the device transmits and watch it fire. Sub-GHz lives in narrow ISM slices well below 1.7 GHz, so a cheap RTL-SDR is enough to see the whole thing — point it at 433.92 MHz (or 315/868/915) and look for the short bursts that appear each time you press the remote or the sensor reports. Two complementary views: a gqrx waterfall shows you the carrier, the modulation shape (OOK looks like blinking blocks, FSK like two stacked lines) and the rough timing; and pointing rtl_433 at the band turns every burst it recognises into a live JSON line naming the device — often the fastest way to confirm what is on the air and on which frequency, before you commit a capture tool. A HackRF works too and reaches the 868/915 bands with margin.", + "note": "Find where the device transmits and watch it fire. Sub-GHz lives in narrow ISM slices well below 1.7 GHz, so a cheap RTL-SDR is enough to see the whole thing, point it at 433.92 MHz (or 315/868/915) and look for the short bursts that appear each time you press the remote or the sensor reports. Two complementary views: a gqrx waterfall shows you the carrier, the modulation shape (OOK looks like blinking blocks, FSK like two stacked lines) and the rough timing; and pointing rtl_433 at the band turns every burst it recognises into a live JSON line naming the device, often the fastest way to confirm what is on the air and on which frequency, before you commit a capture tool. A HackRF works too and reaches the 868/915 bands with margin.", "tools": [ - { "tool": "gqrx", "role": "Spectrum / waterfall view", "why": "See the live sub-GHz spectrum and catch the bursts as you trigger the device — read the exact centre frequency, tell OOK (blinking blocks) from FSK (two parallel lines), and eyeball the burst timing before choosing a capture tool. Cheap and quick on an RTL-SDR since everything here sits below 1 GHz.", "deps": ["rtl-sdr-v4", "hackrf-one"] }, - { "tool": "rtl-433", "role": "Live device scan", "why": "Point rtl_433 at 433.92 MHz (or 315/868/915) and it decodes every burst it recognises into a JSON line naming the device and frequency — the fastest way to inventory what is transmitting around you and confirm a target's band and protocol without reading a waterfall by eye.", "caveat": "Only names devices it already has a decoder for; an unknown gadget still shows energy but no decode — fall back to the waterfall and URH.", "deps": ["rtl-sdr-v4", "hackrf-one"] }, - { "tool": "catnip", "role": "SX1262 spectrum analyzer", "why": "catnip drives the CatSniffer's Semtech SX1262 as a real-time sub-GHz spectrum analyzer — scan the 433/868/915 MHz bands and watch channel activity from the board, no SDR. A CatSniffer-native alternative to the gqrx waterfall for finding where a device transmits.", "deps": ["catsniffer"], "caveat": "A spectrum view to find activity; demodulating the burst is the SDR + rtl_433/URH or the CatSniffer (G)FSK path at the Capture step." } + { "tool": "gqrx", "role": "Spectrum / waterfall view", "why": "See the live sub-GHz spectrum and catch the bursts as you trigger the device, read the exact centre frequency, tell OOK (blinking blocks) from FSK (two parallel lines), and eyeball the burst timing before choosing a capture tool. Cheap and quick on an RTL-SDR since everything here sits below 1 GHz.", "deps": ["rtl-sdr-v4", "hackrf-one"] }, + { "tool": "rtl-433", "role": "Live device scan", "why": "Point rtl_433 at 433.92 MHz (or 315/868/915) and it decodes every burst it recognises into a JSON line naming the device and frequency, the fastest way to inventory what is transmitting around you and confirm a target's band and protocol without reading a waterfall by eye.", "caveat": "Only names devices it already has a decoder for; an unknown gadget still shows energy but no decode, fall back to the waterfall and URH.", "deps": ["rtl-sdr-v4", "hackrf-one"] }, + { "tool": "catnip", "role": "SX1262 spectrum analyzer", "why": "catnip drives the CatSniffer's Semtech SX1262 as a real-time sub-GHz spectrum analyzer, scan the 433/868/915 MHz bands and watch channel activity from the board, no SDR. A CatSniffer-native alternative to the gqrx waterfall for finding where a device transmits.", "deps": ["catsniffer"], "caveat": "A spectrum view to find activity; demodulating the burst is the SDR + rtl_433/URH or the CatSniffer (G)FSK path at the Capture step." } ] }, "PHY": { - "note": "No separate hardware demodulator step here — sub-GHz waveforms are simple (OOK/ASK or FSK at low baud), so the capture tools demodulate and frame in one pass and live at the next step. The PHY job is just a clean recording: sample the burst at a rate that comfortably covers its bandwidth, centred on the carrier you found at the Spectrum step, so the on/off edges (OOK) or the two tones (FSK) come through crisply for the demodulator to slice into bits." + "note": "No separate hardware demodulator step here, sub-GHz waveforms are simple (OOK/ASK or FSK at low baud), so the capture tools demodulate and frame in one pass and live at the next step. The PHY job is just a clean recording: sample the burst at a rate that comfortably covers its bandwidth, centred on the carrier you found at the Spectrum step, so the on/off edges (OOK) or the two tones (FSK) come through crisply for the demodulator to slice into bits." }, "LL": { - "note": "Capture the burst and turn it into bits and fields. For the OOK/ASK remotes that fill this band there is no PCAP-and-Wireshark flow — the radio tool is its own decoder. Three honest paths by how much the device is already understood: if it is a known device class, rtl_433 demodulates and decodes it straight to named JSON fields (ID, sensor values, checksum) — capture and decode in one command. If it is unknown, Universal Radio Hacker is the workbench: record the I/Q off an SDR, let it auto-detect the modulation and baud, extract the bitstream and label the fields by diffing several captures (e.g. press the button twice and see what changes). And for hands-on RX/TX from a pocket transceiver, rfcat drives a YARD Stick One to receive (and later replay) OOK/ASK/FSK from a Python shell, while the Flipper Zero captures a signal standalone — Read decodes a known protocol, Read RAW saves an unknown one for replay — with no laptop at all. The CatSniffer is the board exception: its Semtech SX1262 reads — and later transmits — (G)FSK packets on 433/868/915 MHz over a scriptable serial bridge, and its CC1352P firmware captures IEEE 802.15.4g (plus LoRa/Meshtastic) into Wireshark via catnip — covering the FSK/GFSK and framed device classes the SDR + rtl_433 OOK/ASK flow doesn’t.", + "note": "Capture the burst and turn it into bits and fields. For the OOK/ASK remotes that fill this band there is no PCAP-and-Wireshark flow, the radio tool is its own decoder. Three honest paths by how much the device is already understood: if it is a known device class, rtl_433 demodulates and decodes it straight to named JSON fields (ID, sensor values, checksum), capture and decode in one command. If it is unknown, Universal Radio Hacker is the workbench: record the I/Q off an SDR, let it auto-detect the modulation and baud, extract the bitstream and label the fields by diffing several captures (e.g. press the button twice and see what changes). And for hands-on RX/TX from a pocket transceiver, rfcat drives a YARD Stick One to receive (and later replay) OOK/ASK/FSK from a Python shell, while the Flipper Zero captures a signal standalone, Read decodes a known protocol, Read RAW saves an unknown one for replay, with no laptop at all. The CatSniffer is the board exception: its Semtech SX1262 reads, and later transmits, (G)FSK packets on 433/868/915 MHz over a scriptable serial bridge, and its CC1352P firmware captures IEEE 802.15.4g (plus LoRa/Meshtastic) into Wireshark via catnip, covering the FSK/GFSK and framed device classes the SDR + rtl_433 OOK/ASK flow doesn’t.", "tools": [ - { "tool": "rtl-433", "role": "Primary decoder (known devices)", "why": "For any of its 320+ supported device protocols, rtl_433 demodulates the OOK/ASK or FSK burst and decodes it to named JSON fields in one step — the ID, the sensor/state values and the checksum — so a known TPMS, weather sensor or doorbell is captured and fully parsed at once. The default capture tool when the device is a recognised class.", "caveat": "Decodes only devices it has a protocol for; an unknown or proprietary remote needs URH instead.", "deps": ["rtl-sdr-v4", "hackrf-one"] }, - { "tool": "universal-radio-hacker", "role": "Reverse unknown signals", "why": "The workhorse for anything rtl_433 can't name: record the I/Q off an SDR, auto-detect modulation and bit rate, extract the bitstream, and diff several captures to label the fields (preamble, ID, payload, checksum). The fastest path from a raw OOK/FSK burst to a understood frame format — and it can resend what it captured.", "caveat": "Repository is archived (still the de-facto unknown-signal tool); a sample rate that covers the burst bandwidth matters.", "deps": ["hackrf-one", "rtl-sdr-v4", "yard-stick-one"] }, - { "tool": "rfcat", "role": "Pocket RX/TX (Python shell)", "why": "Drives a YARD Stick One as a CC1111 sub-GHz transceiver from a Python shell: set the frequency, modulation and baud you found, receive a burst and later replay or forge it — the reference cheap, scriptable sub-GHz work tool without an SDR.", "deps": ["yard-stick-one"] }, - { "tool": "flipperzero-firmware", "role": "Standalone field capture", "why": "The Flipper Zero's Sub-GHz app captures a signal standalone on its CC1101 radio — Read decodes a known protocol on the spot, Read RAW saves an unknown signal's raw timings — so you grab a remote in the field with no laptop or SDR and carry it straight to the replay step.", "caveat": "Official firmware will not save or replay rolling-code signals (a deliberate safety limit); fixed-code only on stock firmware.", "deps": ["flipper-zero"] }, - { "tool": "catnip", "role": "(G)FSK packet RX (scriptable)", "why": "The CatSniffer's Semtech SX1262 is a sub-1 GHz transceiver that does (G)FSK as well as LoRa, so catnip's SX1262 frame driver reads (G)FSK packets on 433/868/915 MHz over the serial bridge — scriptable in Python — and the CC1352P sniffer firmware additionally captures IEEE 802.15.4g (Wi-SUN / smart-meter mesh) and LoRa/Meshtastic into Wireshark. A board-based packet path for the many FSK/GFSK sub-GHz devices, no SDR.", "deps": ["catsniffer"], "caveat": "Reads framed (G)FSK packets — you set the frequency, modulation and bitrate; arbitrary OOK/ASK remotes still need the SDR + rtl_433/URH path. Captured packets can be transmitted back at the Attack step." } + { "tool": "rtl-433", "role": "Primary decoder (known devices)", "why": "For any of its 320+ supported device protocols, rtl_433 demodulates the OOK/ASK or FSK burst and decodes it to named JSON fields in one step, the ID, the sensor/state values and the checksum, so a known TPMS, weather sensor or doorbell is captured and fully parsed at once. The default capture tool when the device is a recognised class.", "caveat": "Decodes only devices it has a protocol for; an unknown or proprietary remote needs URH instead.", "deps": ["rtl-sdr-v4", "hackrf-one"] }, + { "tool": "universal-radio-hacker", "role": "Reverse unknown signals", "why": "The workhorse for anything rtl_433 can't name: record the I/Q off an SDR, auto-detect modulation and bit rate, extract the bitstream, and diff several captures to label the fields (preamble, ID, payload, checksum). The fastest path from a raw OOK/FSK burst to a understood frame format, and it can resend what it captured.", "caveat": "Repository is archived (still the de-facto unknown-signal tool); a sample rate that covers the burst bandwidth matters.", "deps": ["hackrf-one", "rtl-sdr-v4", "yard-stick-one"] }, + { "tool": "rfcat", "role": "Pocket RX/TX (Python shell)", "why": "Drives a YARD Stick One as a CC1111 sub-GHz transceiver from a Python shell: set the frequency, modulation and baud you found, receive a burst and later replay or forge it, the reference cheap, scriptable sub-GHz work tool without an SDR.", "deps": ["yard-stick-one"] }, + { "tool": "flipperzero-firmware", "role": "Standalone field capture", "why": "The Flipper Zero's Sub-GHz app captures a signal standalone on its CC1101 radio, Read decodes a known protocol on the spot, Read RAW saves an unknown signal's raw timings, so you grab a remote in the field with no laptop or SDR and carry it straight to the replay step.", "caveat": "Official firmware will not save or replay rolling-code signals (a deliberate safety limit); fixed-code only on stock firmware.", "deps": ["flipper-zero"] }, + { "tool": "catnip", "role": "(G)FSK packet RX (scriptable)", "why": "The CatSniffer's Semtech SX1262 is a sub-1 GHz transceiver that does (G)FSK as well as LoRa, so catnip's SX1262 frame driver reads (G)FSK packets on 433/868/915 MHz over the serial bridge, scriptable in Python, and the CC1352P sniffer firmware additionally captures IEEE 802.15.4g (Wi-SUN / smart-meter mesh) and LoRa/Meshtastic into Wireshark. A board-based packet path for the many FSK/GFSK sub-GHz devices, no SDR.", "deps": ["catsniffer"], "caveat": "Reads framed (G)FSK packets, you set the frequency, modulation and bitrate; arbitrary OOK/ASK remotes still need the SDR + rtl_433/URH path. Captured packets can be transmitted back at the Attack step." } ] }, "CR": { - "note": "Be honest: for most sub-GHz devices there is nothing to 'crack', because there is no confidentiality to break. Fixed-code remotes and sensors transmit their payload in the clear — you read it at the Capture step, you do not decrypt it. The one thing that looks like crypto is the rolling code (KeeLoq / HCS301 and similar): each press sends a fresh value so an old capture won't replay, but that is replay resistance, not an encrypted channel you recover plaintext from. A rolling code is defeated by capturing and replaying a code the receiver hasn't seen yet (the Attack step), not by an offline break — and to truly forge the next valid code you would need the manufacturer's secret key programmed into the chip, which a passive capture never reveals. KeeLoq has known academic cryptanalysis (correlation/side-channel attacks to recover that manufacturer key), but those require physical or large-scale access far beyond a capture and are out of scope for this RF toolchain. So: read fixed codes, capture-and-replay rolling codes — there is no general offline cracker to point at sub-GHz." + "note": "Be honest: for most sub-GHz devices there is nothing to 'crack', because there is no confidentiality to break. Fixed-code remotes and sensors transmit their payload in the clear, you read it at the Capture step, you do not decrypt it. The one thing that looks like crypto is the rolling code (KeeLoq / HCS301 and similar): each press sends a fresh value so an old capture won't replay, but that is replay resistance, not an encrypted channel you recover plaintext from. A rolling code is defeated by capturing and replaying a code the receiver hasn't seen yet (the Attack step), not by an offline break, and to truly forge the next valid code you would need the manufacturer's secret key programmed into the chip, which a passive capture never reveals. KeeLoq has known academic cryptanalysis (correlation/side-channel attacks to recover that manufacturer key), but those require physical or large-scale access far beyond a capture and are out of scope for this RF toolchain. So: read fixed codes, capture-and-replay rolling codes, there is no general offline cracker to point at sub-GHz." }, "AT": { - "note": "Going active means transmitting on the device's frequency to take over its function — do this ONLY on equipment you own or are explicitly authorised to test, and mind that even unlicensed ISM bands have power and duty-cycle rules. The attacks follow straight from the code type you identified. For a FIXED-code device the attack is trivial: replay the captured burst and the receiver acts on it (a gate opens, a sensor reading is spoofed) — re-send it with rfcat on a YARD Stick One, with URH's transmit, from a Flipper Zero, or generate it on a HackRF. For a ROLLING-code device a naive replay fails, so the classic technique is RollJam-style capture-and-block: jam the receiver while recording the victim's first press (so the device never acts on it and the code stays unused), let them press again and capture that too, forward the first code to operate the device now, and keep the second unused code to operate it later — a captured-but-unused valid code, not a broken cipher. Related techniques include de-syncing a rolling-code counter by replaying many codes to push it out of the receiver's window (denial of service), and brute-forcing a small fixed-code keyspace (e.g. 8–12 DIP-switch bits on old EV1527/PT2262 remotes). All of these need a transmit-capable radio.", + "note": "Going active means transmitting on the device's frequency to take over its function, do this ONLY on equipment you own or are explicitly authorised to test, and mind that even unlicensed ISM bands have power and duty-cycle rules. The attacks follow straight from the code type you identified. For a FIXED-code device the attack is trivial: replay the captured burst and the receiver acts on it (a gate opens, a sensor reading is spoofed), re-send it with rfcat on a YARD Stick One, with URH's transmit, from a Flipper Zero, or generate it on a HackRF. For a ROLLING-code device a naive replay fails, so the classic technique is RollJam-style capture-and-block: jam the receiver while recording the victim's first press (so the device never acts on it and the code stays unused), let them press again and capture that too, forward the first code to operate the device now, and keep the second unused code to operate it later, a captured-but-unused valid code, not a broken cipher. Related techniques include de-syncing a rolling-code counter by replaying many codes to push it out of the receiver's window (denial of service), and brute-forcing a small fixed-code keyspace (e.g. 8 to 12 DIP-switch bits on old EV1527/PT2262 remotes). All of these need a transmit-capable radio.", "tools": [ - { "tool": "rfcat", "role": "Replay & transmit (fixed code)", "why": "From the Python shell, set the exact frequency/modulation/baud and re-transmit a captured fixed-code burst (or brute-force a short DIP-switch keyspace) through a YARD Stick One — the simplest replay against a fixed-code remote, gate or sensor.", "deps": ["yard-stick-one"], "needs": "The captured burst / decoded bits from the Capture step to re-send. Authorised testing only." }, - { "tool": "universal-radio-hacker", "role": "Replay & crafted-frame TX", "why": "URH transmits what it captured and lets you edit the bits first — flip a field, fix a checksum, fuzz a value — then send it on a TX-capable SDR or a YARD Stick One. The bridge from reversing an unknown frame to actively testing how the receiver responds to it.", "caveat": "Archived repo; transmits — authorised testing only.", "deps": ["hackrf-one", "yard-stick-one"], "needs": "A captured/edited frame from the Capture step and a transmit-capable radio." }, - { "tool": "flipperzero-firmware", "role": "Field replay (fixed code)", "why": "Replay a saved fixed-code signal from the Flipper Zero's Sub-GHz app in the field — open the gate or trigger the device you captured, no laptop needed.", "caveat": "Stock firmware refuses to save/replay rolling codes by design; fixed-code replay only without custom firmware.", "deps": ["flipper-zero"], "needs": "A signal saved at the Capture step. Authorised testing only." }, - { "tool": "catnip", "role": "(G)FSK transmit / replay (scriptable)", "why": "The CatSniffer's SX1262 transmits as well as receives, so it can re-send a captured (G)FSK packet — or a crafted one — on 433/868/915 MHz over the serial bridge, scriptable in Python: read a packet at the Capture step, then transmit it later to test replay or fuzzing against an FSK/GFSK device. A pocket transmit-capable sub-GHz board, no SDR.", "deps": ["catsniffer"], "needs": "A captured or crafted (G)FSK packet from the Capture step plus the target's frequency/modulation/bitrate. Transmits on ISM bands — authorised testing only, and mind power/duty-cycle limits.", "caveat": "(G)FSK packets, not arbitrary OOK/ASK signalling." } + { "tool": "rfcat", "role": "Replay & transmit (fixed code)", "why": "From the Python shell, set the exact frequency/modulation/baud and re-transmit a captured fixed-code burst (or brute-force a short DIP-switch keyspace) through a YARD Stick One, the simplest replay against a fixed-code remote, gate or sensor.", "deps": ["yard-stick-one"], "needs": "The captured burst / decoded bits from the Capture step to re-send. Authorised testing only." }, + { "tool": "universal-radio-hacker", "role": "Replay & crafted-frame TX", "why": "URH transmits what it captured and lets you edit the bits first, flip a field, fix a checksum, fuzz a value, then send it on a TX-capable SDR or a YARD Stick One. The bridge from reversing an unknown frame to actively testing how the receiver responds to it.", "caveat": "Archived repo; transmits, authorised testing only.", "deps": ["hackrf-one", "yard-stick-one"], "needs": "A captured/edited frame from the Capture step and a transmit-capable radio." }, + { "tool": "flipperzero-firmware", "role": "Field replay (fixed code)", "why": "Replay a saved fixed-code signal from the Flipper Zero's Sub-GHz app in the field, open the gate or trigger the device you captured, no laptop needed.", "caveat": "Stock firmware refuses to save/replay rolling codes by design; fixed-code replay only without custom firmware.", "deps": ["flipper-zero"], "needs": "A signal saved at the Capture step. Authorised testing only." }, + { "tool": "catnip", "role": "(G)FSK transmit / replay (scriptable)", "why": "The CatSniffer's SX1262 transmits as well as receives, so it can re-send a captured (G)FSK packet, or a crafted one, on 433/868/915 MHz over the serial bridge, scriptable in Python: read a packet at the Capture step, then transmit it later to test replay or fuzzing against an FSK/GFSK device. A pocket transmit-capable sub-GHz board, no SDR.", "deps": ["catsniffer"], "needs": "A captured or crafted (G)FSK packet from the Capture step plus the target's frequency/modulation/bitrate. Transmits on ISM bands, authorised testing only, and mind power/duty-cycle limits.", "caveat": "(G)FSK packets, not arbitrary OOK/ASK signalling." } ] }, "AP": { - "note": "Above the radio burst, the 'application' of a sub-GHz device is just the meaning of the bytes it sends — a TPMS reporting pressure and temperature, a weather station sending humidity, a contact sensor saying open/closed, a meter sending consumption. There is no separate protocol stack to attack: rtl_433 already decodes hundreds of these device classes into named JSON fields, so reading the application layer is reading (and, at the Attack step, spoofing) those fields. Point rtl_433 at the device and its JSON output is the application view — the sensor values, IDs and flags the receiver trusts — which is exactly what you forge or replay to make a gateway or display believe a fake reading.", + "note": "Above the radio burst, the 'application' of a sub-GHz device is just the meaning of the bytes it sends, a TPMS reporting pressure and temperature, a weather station sending humidity, a contact sensor saying open/closed, a meter sending consumption. There is no separate protocol stack to attack: rtl_433 already decodes hundreds of these device classes into named JSON fields, so reading the application layer is reading (and, at the Attack step, spoofing) those fields. Point rtl_433 at the device and its JSON output is the application view, the sensor values, IDs and flags the receiver trusts, which is exactly what you forge or replay to make a gateway or display believe a fake reading.", "tools": [ - { "tool": "rtl-433", "role": "Decoded device semantics (JSON)", "why": "rtl_433's JSON output is the application layer for sub-GHz sensors and remotes: each decoded burst becomes named fields — device ID, temperature/pressure/humidity, battery, open/closed, button — so you can read exactly what the receiver acts on, and know precisely which values to spoof or replay to drive it. The same decode that captured the device also exposes its semantics.", "deps": ["rtl-sdr-v4", "hackrf-one"], "needs": "The live device (or a recording) on a receive radio; rtl_433 prints the decoded fields as JSON for inspection or logging." } + { "tool": "rtl-433", "role": "Decoded device semantics (JSON)", "why": "rtl_433's JSON output is the application layer for sub-GHz sensors and remotes: each decoded burst becomes named fields, device ID, temperature/pressure/humidity, battery, open/closed, button, so you can read exactly what the receiver acts on, and know precisely which values to spoof or replay to drive it. The same decode that captured the device also exposes its semantics.", "deps": ["rtl-sdr-v4", "hackrf-one"], "needs": "The live device (or a recording) on a receive radio; rtl_433 prints the decoded fields as JSON for inspection or logging." } ] } } diff --git a/src/data/toolchains/thread.js b/src/data/toolchains/thread.js index 5812f00..5442905 100644 --- a/src/data/toolchains/thread.js +++ b/src/data/toolchains/thread.js @@ -1,10 +1,10 @@ export default { "status": "complete", "facts": [ - { "k": "Band", "v": "2.4 GHz ISM — IEEE 802.15.4 O-QPSK PHY, the same radio layer as Zigbee" }, - { "k": "Channels", "v": "16 × 5 MHz, channels 11–26 (2.405–2.480 GHz); a Thread network sits on one channel" }, + { "k": "Band", "v": "2.4 GHz ISM, IEEE 802.15.4 O-QPSK PHY, the same radio layer as Zigbee" }, + { "k": "Channels", "v": "16 × 5 MHz, channels 11 to 26 (2.405 to 2.480 GHz); a Thread network sits on one channel" }, { "k": "Stack", "v": "IPv6 mesh: 802.15.4 MAC → 6LoWPAN header compression → MLE (Mesh Link Establishment) routing → UDP. Matter (CHIP) rides on top." }, - { "k": "Thread security", "v": "MAC-layer AES-128-CCM* keyed by the Thread network key — strong link crypto. Commissioning: Commissioner authenticates with PSKc; a Joiner is admitted with PSKd over DTLS." }, + { "k": "Thread security", "v": "MAC-layer AES-128-CCM* keyed by the Thread network key, strong link crypto. Commissioning: Commissioner authenticates with PSKc; a Joiner is admitted with PSKd over DTLS." }, { "k": "Matter transport", "v": "Runs over Thread (via a Border Router) or Wi-Fi; commissioned over Bluetooth LE. Discoverable by DNS-SD: _matterc._udp = commissionable, _matter._tcp = operational, _meshcop._udp = a Thread Border Router." }, { "k": "Matter onboarding", "v": "QR (MT: prefix, Base-38) / 11-digit manual code carry a 27-bit setup passcode + 12-bit discriminator (manual code only the upper 4-bit short discriminator), plus 16-bit Vendor ID and 16-bit Product ID." }, { "k": "Matter crypto", "v": "PASE = SPAKE2+ (P-256) keyed from the setup passcode, only during the commissioning window; CASE = certificate-authenticated (NOC under a fabric Root CA, SIGMA over P-256) for all operational sessions. The passcode is the weak link, not the cipher." } @@ -12,64 +12,64 @@ export default { "reference": null, "layers": { "IG": { - "note": "Identify the mesh before any RF work — and first settle what you are even looking at. Thread and Zigbee share the exact same IEEE 802.15.4 2.4 GHz PHY, so a spectrum view alone cannot tell them apart; you distinguish them by what rides on top. Thread is an IPv6 mesh — its frames carry 6LoWPAN-compressed IPv6 and MLE link-management messages — whereas Zigbee carries its own NWK/APS layers. If the device is a Matter product, almost everything you need is in plain sight: a setup QR code / 11-digit numeric setup code on the label, a BLE radio used only for onboarding, and a transport you can read from DNS-SD — _matterc._udp means it is commissionable (waiting), _matter._tcp means it is already on a fabric, and a nearby _meshcop._udp means there is a Thread Border Router, so it is Matter-over-Thread rather than Matter-over-Wi-Fi. The onboarding payload itself carries the Vendor ID and Product ID, which the Distributed Compliance Ledger (DCL) resolves to a known vendor, product and certification record. The honest headline: Thread's link crypto and Matter's operational crypto are both strong, so the real attack surface is commissioning, weak or exposed setup codes, and the BLE onboarding window — not breaking AES.", + "note": "Identify the mesh before any RF work, and first settle what you are even looking at. Thread and Zigbee share the exact same IEEE 802.15.4 2.4 GHz PHY, so a spectrum view alone cannot tell them apart; you distinguish them by what rides on top. Thread is an IPv6 mesh, its frames carry 6LoWPAN-compressed IPv6 and MLE link-management messages, whereas Zigbee carries its own NWK/APS layers. If the device is a Matter product, almost everything you need is in plain sight: a setup QR code / 11-digit numeric setup code on the label, a BLE radio used only for onboarding, and a transport you can read from DNS-SD, _matterc._udp means it is commissionable (waiting), _matter._tcp means it is already on a fabric, and a nearby _meshcop._udp means there is a Thread Border Router, so it is Matter-over-Thread rather than Matter-over-Wi-Fi. The onboarding payload itself carries the Vendor ID and Product ID, which the Distributed Compliance Ledger (DCL) resolves to a known vendor, product and certification record. The honest headline: Thread's link crypto and Matter's operational crypto are both strong, so the real attack surface is commissioning, weak or exposed setup codes, and the BLE onboarding window, not breaking AES.", "lookFor": [ - "Is it Thread or Zigbee? Both are 802.15.4 at 2.4 GHz — tell them apart by the upper layers: 6LoWPAN + MLE (and IPv6) means Thread; a Zigbee NWK/APS stack means Zigbee.", + "Is it Thread or Zigbee? Both are 802.15.4 at 2.4 GHz, tell them apart by the upper layers: 6LoWPAN + MLE (and IPv6) means Thread; a Zigbee NWK/APS stack means Zigbee.", "Is it a Matter device, and over which transport? Look for the Matter logo, a setup QR code and an 11-digit numeric setup code on the label, and a BLE radio for onboarding. Read the transport from DNS-SD: _matterc._udp = commissionable, _matter._tcp = operational; a co-located _meshcop._udp Border Router means Matter-over-Thread, otherwise it is on Wi-Fi.", - "Decode the onboarding payload (QR 'MT:' Base-38, or the 11-digit manual code): it carries a 27-bit setup passcode, the device discriminator (12-bit, or the upper 4-bit short discriminator in the manual code), the discovery/rendezvous capabilities, and — in the QR / 21-digit manual code — the 16-bit Vendor ID and 16-bit Product ID.", - "Resolve the Vendor ID / Product ID against the Distributed Compliance Ledger (DCL) — vendor and product identity, certification status, and the PAA attestation roots. A Test-Vendor VID (0xFFF1–0xFFF4) on a shipping product is a red flag.", - "Chipset / SoC and SDK (FCC ID, teardown) — e.g. nRF52840, EFR32, ESP32-H2/C6 — and cross-reference known Thread/Matter/802.15.4 stack CVEs (e.g. CASE Sigma1-replay DoS CVE-2024-3297, fabric-footprinting CVE-2024-3454).", - "Network identifiers: the 802.15.4 channel (11–26), PAN ID and Extended PAN ID, and the Network Name — all readable from beacons/MLE without any key.", + "Decode the onboarding payload (QR 'MT:' Base-38, or the 11-digit manual code): it carries a 27-bit setup passcode, the device discriminator (12-bit, or the upper 4-bit short discriminator in the manual code), the discovery/rendezvous capabilities, and, in the QR / 21-digit manual code, the 16-bit Vendor ID and 16-bit Product ID.", + "Resolve the Vendor ID / Product ID against the Distributed Compliance Ledger (DCL), vendor and product identity, certification status, and the PAA attestation roots. A Test-Vendor VID (0xFFF1 to 0xFFF4) on a shipping product is a red flag.", + "Chipset / SoC and SDK (FCC ID, teardown), e.g. nRF52840, EFR32, ESP32-H2/C6, and cross-reference known Thread/Matter/802.15.4 stack CVEs (e.g. CASE Sigma1-replay DoS CVE-2024-3297, fabric-footprinting CVE-2024-3454).", + "Network identifiers: the 802.15.4 channel (11 to 26), PAN ID and Extended PAN ID, and the Network Name, all readable from beacons/MLE without any key.", "Commissioning posture: how is the network key distributed, is a Border Router / Border Agent reachable, and is the commissioning credential (Thread PSKc / Joiner PSKd, or the Matter setup passcode) exposed, default, or weak? Is the BLE commissioning window left open, and can you read the setup passcode off the printed label?" ], "tools": [ - { "tool": "matter-dcl", "role": "Resolve VID/PID & trust roots", "why": "Look up the Vendor ID / Product ID decoded from the onboarding payload against the CSA Distributed Compliance Ledger: who made the device, which product it is, its certification status, and the PAA attestation roots a commissioner trusts — turning the numbers on the QR code into a known device and flagging Test-Vendor VIDs (0xFFF1–0xFFF4).", "deps": [], "needs": "The Vendor ID / Product ID read from the QR or 21-digit manual onboarding payload; query the public DCL web UI or a DCL node. No radio." }, - { "tool": "chip-tool", "role": "Decode payload & discover", "why": "Parse a scanned QR / manual setup code to recover the passcode, discriminator and VID/PID, and discover commissionable Matter nodes over BLE and on-network (DNS-SD) to confirm the transport and that an onboarding window is open — before any commissioning attempt.", "deps": ["usb-bt-dongle", "catsniffer"], "needs": "A host Bluetooth LE adapter for BLE discovery of commissionable devices; for Matter-over-Wi-Fi, on-network DNS-SD discovery needs no BLE radio." } + { "tool": "matter-dcl", "role": "Resolve VID/PID & trust roots", "why": "Look up the Vendor ID / Product ID decoded from the onboarding payload against the CSA Distributed Compliance Ledger: who made the device, which product it is, its certification status, and the PAA attestation roots a commissioner trusts, turning the numbers on the QR code into a known device and flagging Test-Vendor VIDs (0xFFF1 to 0xFFF4).", "deps": [], "needs": "The Vendor ID / Product ID read from the QR or 21-digit manual onboarding payload; query the public DCL web UI or a DCL node. No radio." }, + { "tool": "chip-tool", "role": "Decode payload & discover", "why": "Parse a scanned QR / manual setup code to recover the passcode, discriminator and VID/PID, and discover commissionable Matter nodes over BLE and on-network (DNS-SD) to confirm the transport and that an onboarding window is open, before any commissioning attempt.", "deps": ["usb-bt-dongle", "catsniffer"], "needs": "A host Bluetooth LE adapter for BLE discovery of commissionable devices; for Matter-over-Wi-Fi, on-network DNS-SD discovery needs no BLE radio." } ] }, "SP": { - "note": "How much of the band can you see, and which channel is the mesh on? IEEE 802.15.4 divides the 2.4 GHz band into 16 channels (11–26) of 5 MHz each across roughly 2.405–2.480 GHz, and a Thread network lives on just one of them. The first job is to find that channel. A wide SDR view shows the whole 80 MHz at a glance so you can spot the active channel; you then point a real 802.15.4 radio at it to capture. A HackRF shows ~20 MHz at a time (a few channels); a bladeRF in its oversampling mode covers the full band in one pass. RTL-SDR is out — it stops below the 2.4 GHz band. (Matter's BLE onboarding lives on the BLE advertising channels, not here — that is a Bluetooth LE capture; see the BLE wayfinder.)", + "note": "How much of the band can you see, and which channel is the mesh on? IEEE 802.15.4 divides the 2.4 GHz band into 16 channels (11 to 26) of 5 MHz each across roughly 2.405 to 2.480 GHz, and a Thread network lives on just one of them. The first job is to find that channel. A wide SDR view shows the whole 80 MHz at a glance so you can spot the active channel; you then point a real 802.15.4 radio at it to capture. A HackRF shows ~20 MHz at a time (a few channels); a bladeRF in its oversampling mode covers the full band in one pass. RTL-SDR is out, it stops below the 2.4 GHz band. (Matter's BLE onboarding lives on the BLE advertising channels, not here, that is a Bluetooth LE capture; see the BLE wayfinder.)", "tools": [ - { "tool": "gqrx", "role": "Spectrum / waterfall view", "why": "See the live 2.4 GHz spectrum and pick the active 802.15.4 channel — ~20 MHz at a time on a HackRF, the full band on a bladeRF (oversampling) — before committing a sniffer to it.", "deps": ["hackrf-one", "bladerf-2-micro"] }, + { "tool": "gqrx", "role": "Spectrum / waterfall view", "why": "See the live 2.4 GHz spectrum and pick the active 802.15.4 channel, ~20 MHz at a time on a HackRF, the full band on a bladeRF (oversampling), before committing a sniffer to it.", "deps": ["hackrf-one", "bladerf-2-micro"] }, { "tool": "minino", "role": "Pocket 802.15.4 scanner", "why": "Electronic Cats ESP32-C6 multitool with an 802.15.4 (Zigbee/Thread) field-recon mode: scan channels and spot an active mesh standalone, no laptop or SDR needed.", "caveat": "Recon-level visibility; confirm Thread vs Zigbee from a real frame capture.", "deps": [] }, - { "tool": "catnip", "role": "Channel activity & topology (cativity)", "why": "catnip's cativity monitor shows live 802.15.4 channel activity (11–26) and discovers the network topology of a Thread / Zigbee mesh — a quick CatSniffer-native way to find the active channel and map the mesh before committing a capture radio.", "deps": ["catsniffer"] } + { "tool": "catnip", "role": "Channel activity & topology (cativity)", "why": "catnip's cativity monitor shows live 802.15.4 channel activity (11 to 26) and discovers the network topology of a Thread / Zigbee mesh, a quick CatSniffer-native way to find the active channel and map the mesh before committing a capture radio.", "deps": ["catsniffer"] } ] }, "PHY": { "note": "No standalone Thread demodulator in this kit. The capture tools demodulate the 802.15.4 O-QPSK waveform (PHY) and frame the packets (LL) together on a dedicated 2.4 GHz 802.15.4 radio, so they live at the Capture step. A wide SDR is useful for finding the channel, but a real 802.15.4 transceiver does the actual framing." }, "LL": { - "note": "Capture and decode 802.15.4 / Thread frames. Park a real 802.15.4 radio on the target channel and it pulls the raw frames — beacons, MAC, 6LoWPAN, MLE — into Wireshark, which has a full 802.15.4 + Thread/6LoWPAN/MLE dissector. The crucial trick: Thread's MAC payload is AES-128-CCM* encrypted under the network key, but Wireshark will decrypt it in place once you give it that key (the decrypt step lives in 'Break the crypto'). Pick a capture path: the turnkey Nordic extcap, an OpenThread co-processor via pyspinel, or the standalone Minino. Each runs on its radio and feeds Wireshark. (Matter's BLE commissioning handshake is captured separately as Bluetooth LE traffic — see the BLE wayfinder.)", + "note": "Capture and decode 802.15.4 / Thread frames. Park a real 802.15.4 radio on the target channel and it pulls the raw frames, beacons, MAC, 6LoWPAN, MLE, into Wireshark, which has a full 802.15.4 + Thread/6LoWPAN/MLE dissector. The crucial trick: Thread's MAC payload is AES-128-CCM* encrypted under the network key, but Wireshark will decrypt it in place once you give it that key (the decrypt step lives in 'Break the crypto'). Pick a capture path: the turnkey Nordic extcap, an OpenThread co-processor via pyspinel, or the standalone Minino. Each runs on its radio and feeds Wireshark. (Matter's BLE commissioning handshake is captured separately as Bluetooth LE traffic, see the BLE wayfinder.)", "decoder": "wireshark", "tools": [ - { "tool": "nrf-sniffer-802154", "role": "Primary sniffer", "why": "Nordic's nRF Sniffer for 802.15.4: firmware plus a Wireshark extcap plugin that streams raw 802.15.4/Thread frames straight into Wireshark — the simplest, best-documented capture path. Runs on an nRF52840 dongle.", "deps": ["nrf52840-dongle"] }, - { "tool": "pyspinel", "role": "OpenThread sniffer", "why": "Its sniffer.py turns an OpenThread NCP/RCP into an 802.15.4 sniffer, piping frames to Wireshark — and the same device can also scan for and attempt to join the mesh, so capture and commissioning assessment share one radio.", "deps": ["nrf52840-dongle"], "needs": "An nRF52840 (or other supported radio) flashed with OpenThread as an NCP/RCP; pyspinel drives it over Spinel." }, - { "tool": "catsniffer", "role": "Multiprotocol sniffer", "why": "CC1352-based multiprotocol radio that captures 802.15.4 alongside its BLE/Sub-GHz/Zigbee workflows and exports PCAP for Wireshark — one board for the whole 2.4 GHz mesh kit, and the same board can capture the BLE onboarding traffic.", "deps": [] }, - { "tool": "minino", "role": "Pocket sniffer", "why": "Standalone ESP32-C6 802.15.4 (Zigbee/Thread) capture to microSD with Wireshark-compatible output — capture in the field with no host PC.", "caveat": "2.4 GHz field recon; less control than the host-driven sniffers.", "deps": [] }, - { "tool": "whad", "role": "802.15.4 sniff (multi-protocol)", "why": "WHAD captures raw 802.15.4 — the layer Thread rides on — from an nRF52840 (its Butterfly firmware) or an APIMote into PCAP/Scapy via one Python framework, the same one you use for Zigbee and BLE. Feed the PCAP to Wireshark's Thread/6LoWPAN/MLE dissector.", "deps": ["nrf52840-dongle", "apimote"] } + { "tool": "nrf-sniffer-802154", "role": "Primary sniffer", "why": "Nordic's nRF Sniffer for 802.15.4: firmware plus a Wireshark extcap plugin that streams raw 802.15.4/Thread frames straight into Wireshark, the simplest, best-documented capture path. Runs on an nRF52840 dongle.", "deps": ["nrf52840-dongle"] }, + { "tool": "pyspinel", "role": "OpenThread sniffer", "why": "Its sniffer.py turns an OpenThread NCP/RCP into an 802.15.4 sniffer, piping frames to Wireshark, and the same device can also scan for and attempt to join the mesh, so capture and commissioning assessment share one radio.", "deps": ["nrf52840-dongle"], "needs": "An nRF52840 (or other supported radio) flashed with OpenThread as an NCP/RCP; pyspinel drives it over Spinel." }, + { "tool": "catsniffer", "role": "Multiprotocol sniffer", "why": "CC1352-based multiprotocol radio that captures 802.15.4 alongside its BLE/Sub-GHz/Zigbee workflows and exports PCAP for Wireshark, one board for the whole 2.4 GHz mesh kit, and the same board can capture the BLE onboarding traffic.", "deps": [] }, + { "tool": "minino", "role": "Pocket sniffer", "why": "Standalone ESP32-C6 802.15.4 (Zigbee/Thread) capture to microSD with Wireshark-compatible output, capture in the field with no host PC.", "caveat": "2.4 GHz field recon; less control than the host-driven sniffers.", "deps": [] }, + { "tool": "whad", "role": "802.15.4 sniff (multi-protocol)", "why": "WHAD captures raw 802.15.4, the layer Thread rides on, from an nRF52840 (its Butterfly firmware) or an APIMote into PCAP/Scapy via one Python framework, the same one you use for Zigbee and BLE. Feed the PCAP to Wireshark's Thread/6LoWPAN/MLE dissector.", "deps": ["nrf52840-dongle", "apimote"] } ] }, "CR": { - "note": "Be honest about the crypto: both layers here are strong. Thread's MAC is AES-128-CCM* and Matter's sessions are SPAKE2+ (commissioning) then certificate-authenticated CASE (operation) — there is no offline key-recovery attack the way crackle attacks weak BLE pairing. So this step is decrypt and credential-recovery, not cipher-breaking. On the Thread side: if you hold the Thread network key, Wireshark decrypts the whole capture in place and the mesh becomes readable — the question is whether you can obtain that key from weak/default/exposed commissioning credentials (PSKc / Joiner PSKd). On the Matter side: PASE keys the very first session from the 27-bit setup passcode via SPAKE2+, which is only as strong as that passcode — a default, guessable, or printed-and-photographed passcode collapses the search. The device stores a SPAKE2+ verifier, not the passcode; a verifier extracted from an insecure device is open to offline recovery given the low passcode entropy. Online guessing is rate-limited — a node exits commissioning mode after ~20 failed PASE attempts and the window is time-boxed (≤15 min once on a fabric) — and the spec disallows the obvious codes (00000000, 11111111…, 12345678, 87654321), so the real win is a weak vendor default or an exposed onboarding payload, not brute force against a random code. No radio of its own; it consumes a capture or a recovered verifier.", + "note": "Be honest about the crypto: both layers here are strong. Thread's MAC is AES-128-CCM* and Matter's sessions are SPAKE2+ (commissioning) then certificate-authenticated CASE (operation), there is no offline key-recovery attack the way crackle attacks weak BLE pairing. So this step is decrypt and credential-recovery, not cipher-breaking. On the Thread side: if you hold the Thread network key, Wireshark decrypts the whole capture in place and the mesh becomes readable, the question is whether you can obtain that key from weak/default/exposed commissioning credentials (PSKc / Joiner PSKd). On the Matter side: PASE keys the very first session from the 27-bit setup passcode via SPAKE2+, which is only as strong as that passcode, a default, guessable, or printed-and-photographed passcode collapses the search. The device stores a SPAKE2+ verifier, not the passcode; a verifier extracted from an insecure device is open to offline recovery given the low passcode entropy. Online guessing is rate-limited, a node exits commissioning mode after ~20 failed PASE attempts and the window is time-boxed (≤15 min once on a fabric), and the spec disallows the obvious codes (00000000, 11111111…, 12345678, 87654321), so the real win is a weak vendor default or an exposed onboarding payload, not brute force against a random code. No radio of its own; it consumes a capture or a recovered verifier.", "tools": [ - { "tool": "wireshark", "role": "Decrypt Thread with the network key", "why": "Wireshark's 802.15.4 layer decrypts CCM*-protected Thread frames in place once you supply the Thread network key in its 802.15.4 decryption-keys table — turning an opaque capture into readable 6LoWPAN/MLE/IPv6.", "deps": [], "needs": "A capture of the mesh from the Capture step (nRF Sniffer / pyspinel / CatSniffer / Minino), plus the Thread network key. The key is the prize — it comes from weak/default/exposed commissioning credentials, not from breaking AES." }, - { "tool": "chip-tool", "role": "Matter PASE / passcode test", "why": "Drive PASE (SPAKE2+) against the device with a candidate setup passcode — the default/printed value, or a small guess set — to test whether a weak or exposed passcode lets you establish the first session. Where it succeeds, you can go on to commission the node; where it fails ~20 times the device leaves commissioning mode, which is itself a finding about the rate-limit posture.", "deps": ["usb-bt-dongle", "catsniffer"], "needs": "A host Bluetooth LE adapter (BLE onboarding transport), an open commissioning window, and the candidate setup passcode/discriminator — from the printed QR/label, a known vendor default, or an allowed-range guess. SPAKE2+ has no offline shortcut against a strong random passcode; this targets weak or exposed codes only." } + { "tool": "wireshark", "role": "Decrypt Thread with the network key", "why": "Wireshark's 802.15.4 layer decrypts CCM*-protected Thread frames in place once you supply the Thread network key in its 802.15.4 decryption-keys table, turning an opaque capture into readable 6LoWPAN/MLE/IPv6.", "deps": [], "needs": "A capture of the mesh from the Capture step (nRF Sniffer / pyspinel / CatSniffer / Minino), plus the Thread network key. The key is the prize, it comes from weak/default/exposed commissioning credentials, not from breaking AES." }, + { "tool": "chip-tool", "role": "Matter PASE / passcode test", "why": "Drive PASE (SPAKE2+) against the device with a candidate setup passcode, the default/printed value, or a small guess set, to test whether a weak or exposed passcode lets you establish the first session. Where it succeeds, you can go on to commission the node; where it fails ~20 times the device leaves commissioning mode, which is itself a finding about the rate-limit posture.", "deps": ["usb-bt-dongle", "catsniffer"], "needs": "A host Bluetooth LE adapter (BLE onboarding transport), an open commissioning window, and the candidate setup passcode/discriminator, from the printed QR/label, a known vendor default, or an allowed-range guess. SPAKE2+ has no offline shortcut against a strong random passcode; this targets weak or exposed codes only." } ] }, "AT": { - "note": "The real attack surface is commissioning and fabric onboarding, not the link cipher. Taking over a Thread/Matter device means joining or subverting the mesh or its fabric, not hijacking an established 802.15.4 frame stream. Pick the angle: stand up an OpenThread node and try to join the Thread network using captured/guessed commissioning credentials (then you are inside the mesh and the network key is yours); or attack Matter onboarding directly — run your own commissioner against a device whose BLE commissioning window is open or whose setup passcode is weak/exposed, complete PASE and commission the node onto a fabric you control. Matter is explicitly multi-admin: a device can sit on several fabrics at once, and an existing admin can open a fresh commissioning window (Open Commissioning Window, with a new passcode and verifier) to add a second admin — so the abuse questions are whether that window can be opened or hijacked, whether a freshly issued passcode can be intercepted out-of-band, and whether you can stand up a rogue commissioner during the window. Note the controller is not required to prove trustworthiness to the device, so anyone who clears commissioning becomes a full admin. Where the crypto holds, this credential-and-onboarding path is the way in.", + "note": "The real attack surface is commissioning and fabric onboarding, not the link cipher. Taking over a Thread/Matter device means joining or subverting the mesh or its fabric, not hijacking an established 802.15.4 frame stream. Pick the angle: stand up an OpenThread node and try to join the Thread network using captured/guessed commissioning credentials (then you are inside the mesh and the network key is yours); or attack Matter onboarding directly, run your own commissioner against a device whose BLE commissioning window is open or whose setup passcode is weak/exposed, complete PASE and commission the node onto a fabric you control. Matter is explicitly multi-admin: a device can sit on several fabrics at once, and an existing admin can open a fresh commissioning window (Open Commissioning Window, with a new passcode and verifier) to add a second admin, so the abuse questions are whether that window can be opened or hijacked, whether a freshly issued passcode can be intercepted out-of-band, and whether you can stand up a rogue commissioner during the window. Note the controller is not required to prove trustworthiness to the device, so anyone who clears commissioning becomes a full admin. Where the crypto holds, this credential-and-onboarding path is the way in.", "tools": [ - { "tool": "pyspinel", "role": "Join / probe the mesh", "why": "Drive an OpenThread node to scan, beacon-request and attempt to commission/join the target Thread network using the credentials you obtained — if it joins, you are inside the mesh and hold the network key.", "deps": ["nrf52840-dongle"], "needs": "An nRF52840 flashed with OpenThread (NCP/RCP), plus commissioning credentials (Joiner PSKd / network key) recovered at Identify or Break-the-crypto." }, - { "tool": "chip-tool", "role": "Commission onto your fabric", "why": "Run your own Matter commissioner against the device over BLE: if the commissioning window is open or the setup passcode is weak/exposed, complete PASE and commission the node onto a fabric you control (`pairing ble-thread` / `pairing ble-wifi`, or `pairing code` on-network) — then test multi-admin by opening a second window with `pairing open-commissioning-window`.", "deps": ["usb-bt-dongle", "catsniffer"], "needs": "A host Bluetooth LE adapter for the BLE onboarding transport, and the device's setup passcode/discriminator (from the QR code, label, or a guessable/exposed value). For Matter-over-Thread you also supply the Thread operational dataset; for Matter-over-Wi-Fi, the Wi-Fi SSID/credentials." }, - { "tool": "chip-repl", "role": "Scripted multi-fabric abuse", "why": "Same CHIP controller stack as chip-tool but in Python — script repeated PASE attempts, automate commissioning onto an attacker fabric, and drive multi-admin / multi-fabric tests (open a window, add a second admin, enumerate fabrics) programmatically rather than by hand.", "deps": ["usb-bt-dongle", "catsniffer"], "needs": "A host Bluetooth LE adapter for BLE onboarding and the device's setup passcode/discriminator; the connectedhomeip Python controller (matter-repl.py)." } + { "tool": "pyspinel", "role": "Join / probe the mesh", "why": "Drive an OpenThread node to scan, beacon-request and attempt to commission/join the target Thread network using the credentials you obtained, if it joins, you are inside the mesh and hold the network key.", "deps": ["nrf52840-dongle"], "needs": "An nRF52840 flashed with OpenThread (NCP/RCP), plus commissioning credentials (Joiner PSKd / network key) recovered at Identify or Break-the-crypto." }, + { "tool": "chip-tool", "role": "Commission onto your fabric", "why": "Run your own Matter commissioner against the device over BLE: if the commissioning window is open or the setup passcode is weak/exposed, complete PASE and commission the node onto a fabric you control (`pairing ble-thread` / `pairing ble-wifi`, or `pairing code` on-network), then test multi-admin by opening a second window with `pairing open-commissioning-window`.", "deps": ["usb-bt-dongle", "catsniffer"], "needs": "A host Bluetooth LE adapter for the BLE onboarding transport, and the device's setup passcode/discriminator (from the QR code, label, or a guessable/exposed value). For Matter-over-Thread you also supply the Thread operational dataset; for Matter-over-Wi-Fi, the Wi-Fi SSID/credentials." }, + { "tool": "chip-repl", "role": "Scripted multi-fabric abuse", "why": "Same CHIP controller stack as chip-tool but in Python, script repeated PASE attempts, automate commissioning onto an attacker fabric, and drive multi-admin / multi-fabric tests (open a window, add a second admin, enumerate fabrics) programmatically rather than by hand.", "deps": ["usb-bt-dongle", "catsniffer"], "needs": "A host Bluetooth LE adapter for BLE onboarding and the device's setup passcode/discriminator; the connectedhomeip Python controller (matter-repl.py)." } ] }, "AP": { - "note": "Once you are commissioned onto the device (or onto the mesh), test what it exposes above the link. For Matter that is the cluster/attribute model — read state, invoke commands, subscribe to reports — all over CASE-secured operational sessions. The questions here are what the device trusts a commissioned controller to do, whether its Access Control List (ACL) actually constrains a freshly added admin, and whether the application layer enforces the access controls Matter's spec expects. Because commissioning makes you a full fabric admin, the application layer is often wide open to a controller that got in — which is exactly why the commissioning gate matters so much.", + "note": "Once you are commissioned onto the device (or onto the mesh), test what it exposes above the link. For Matter that is the cluster/attribute model, read state, invoke commands, subscribe to reports, all over CASE-secured operational sessions. The questions here are what the device trusts a commissioned controller to do, whether its Access Control List (ACL) actually constrains a freshly added admin, and whether the application layer enforces the access controls Matter's spec expects. Because commissioning makes you a full fabric admin, the application layer is often wide open to a controller that got in, which is exactly why the commissioning gate matters so much.", "tools": [ - { "tool": "chip-tool", "role": "Matter cluster interaction", "why": "After commissioning, use CASE-secured operational commands to read/write attributes, invoke cluster commands and subscribe to a Matter device — the way to enumerate and exercise its application layer and probe its Access Control List.", "deps": ["usb-bt-dongle", "catsniffer"], "needs": "A commissioned Matter node (from the Attack step) and a controller fabric; chip-tool from the connectedhomeip SDK speaks the operational Matter protocol over Thread or Wi-Fi (the BLE adapter is only needed for the initial commissioning)." }, - { "tool": "chip-repl", "role": "Scripted cluster enumeration", "why": "Walk the whole cluster/attribute tree, batch reads and subscriptions, and replay learned commands from Python — better than chip-tool for systematically enumerating a device's exposed application surface and access controls.", "deps": ["usb-bt-dongle", "catsniffer"], "needs": "A commissioned Matter node and the connectedhomeip Python controller; operational traffic rides Thread or Wi-Fi, so no BLE radio is needed post-commissioning." }, - { "tool": "python-matter-server", "role": "Standing controller / API", "why": "Run a persistent CSA-certified Matter controller (the one behind Home Assistant) and drive the commissioned node over its WebSocket API — convenient when you want a long-lived controller to enumerate clusters, watch subscriptions over time, and integrate the device into a test harness.", "deps": ["usb-bt-dongle", "catsniffer"], "needs": "A commissioned Matter node and a host with the CHIP stack; a BLE adapter only if you also use it to perform the initial commissioning. Operational interaction is over Thread/Wi-Fi." } + { "tool": "chip-tool", "role": "Matter cluster interaction", "why": "After commissioning, use CASE-secured operational commands to read/write attributes, invoke cluster commands and subscribe to a Matter device, the way to enumerate and exercise its application layer and probe its Access Control List.", "deps": ["usb-bt-dongle", "catsniffer"], "needs": "A commissioned Matter node (from the Attack step) and a controller fabric; chip-tool from the connectedhomeip SDK speaks the operational Matter protocol over Thread or Wi-Fi (the BLE adapter is only needed for the initial commissioning)." }, + { "tool": "chip-repl", "role": "Scripted cluster enumeration", "why": "Walk the whole cluster/attribute tree, batch reads and subscriptions, and replay learned commands from Python, better than chip-tool for systematically enumerating a device's exposed application surface and access controls.", "deps": ["usb-bt-dongle", "catsniffer"], "needs": "A commissioned Matter node and the connectedhomeip Python controller; operational traffic rides Thread or Wi-Fi, so no BLE radio is needed post-commissioning." }, + { "tool": "python-matter-server", "role": "Standing controller / API", "why": "Run a persistent CSA-certified Matter controller (the one behind Home Assistant) and drive the commissioned node over its WebSocket API, convenient when you want a long-lived controller to enumerate clusters, watch subscriptions over time, and integrate the device into a test harness.", "deps": ["usb-bt-dongle", "catsniffer"], "needs": "A commissioned Matter node and a host with the CHIP stack; a BLE adapter only if you also use it to perform the initial commissioning. Operational interaction is over Thread/Wi-Fi." } ] } } diff --git a/src/data/toolchains/uwb.js b/src/data/toolchains/uwb.js index 83c81e2..19f6aa9 100644 --- a/src/data/toolchains/uwb.js +++ b/src/data/toolchains/uwb.js @@ -1,9 +1,9 @@ export default { "status": "complete", "facts": [ - { "k": "Band", "v": "Impulse-radio UWB, ~3.1–10.6 GHz, >500 MHz of channel bandwidth per pulse. In practice two channels dominate: channel 5 at 6.5 GHz and channel 9 at 8.0 GHz." }, - { "k": "Standard", "v": "IEEE 802.15.4z, two incompatible PHYs: HRP (High Rate Pulse-repetition, ~64/124.8 MHz PRF — the one in phones/cars) and LRP (Low Rate Pulse, used by NXP/3db designs). Plus legacy 802.15.4-2011/4a (the older DW1000 generation, no STS)." }, - { "k": "Modulation", "v": "Impulse radio: very short (sub-nanosecond) RF pulses, not a continuous carrier. Bit rates 850 kbps / 6.81 Mbps. Time-of-flight of the pulses — not signal strength — is what yields distance, which is why it is so hard to spoof and so precise (~10 cm)." }, + { "k": "Band", "v": "Impulse-radio UWB, ~3.1 to 10.6 GHz, >500 MHz of channel bandwidth per pulse. In practice two channels dominate: channel 5 at 6.5 GHz and channel 9 at 8.0 GHz." }, + { "k": "Standard", "v": "IEEE 802.15.4z, two incompatible PHYs: HRP (High Rate Pulse-repetition, ~64/124.8 MHz PRF, the one in phones/cars) and LRP (Low Rate Pulse, used by NXP/3db designs). Plus legacy 802.15.4-2011/4a (the older DW1000 generation, no STS)." }, + { "k": "Modulation", "v": "Impulse radio: very short (sub-nanosecond) RF pulses, not a continuous carrier. Bit rates 850 kbps / 6.81 Mbps. Time-of-flight of the pulses, not signal strength, is what yields distance, which is why it is so hard to spoof and so precise (~10 cm)." }, { "k": "Purpose", "v": "Secure ranging / distance bounding and precise positioning, NOT bulk data. Two-Way Ranging (TWR), TDoA and PDoA/AoA. Used for Apple U1/U2 (AirTag, iPhone Nearby Interaction), CCC Digital Key car access, Samsung SmartTag+, FiRa RTLS." }, { "k": "Security", "v": "802.15.4z adds the STS (Scrambled Timestamp Sequence): an AES-keyed pseudo-random pulse sequence the receiver correlates against to authenticate the ranging timestamp, so an attacker cannot forge or replay a legitimate-looking ranging pulse. The research surface is therefore PHYSICAL-LAYER distance manipulation (early-detect / preamble-injection on the impulse waveform), NOT cracking the AES key." }, { "k": "Schemes", "v": "Same radio, different application protocols on top: Apple Nearby Interaction (U1/U2), the Car Connectivity Consortium (CCC) Digital Key, and FiRa (the cross-vendor RTLS/ranging consortium). Which scheme is running decides the frame format and ranging-round structure you must match to capture it." } @@ -11,43 +11,43 @@ export default { "reference": null, "layers": { "IG": { - "note": "Work out what the UWB device is before touching the air — there is no capture yet, and UWB has more forks than most protocols. First the silicon: a Qorvo/Decawave DW1000 is the OLD generation (legacy 802.15.4-2011, no STS security) while a DW3000 (DW3110/DW3210) is the modern 802.15.4z part with STS; NXP Trimension (SR040/SR150) and Apple's own U1/U2 are the other major families. Then the PHY: HRP UWB (the one in iPhones, AirTags and car keys) versus the rarer LRP. Then the channel: nearly everything is channel 5 (6.5 GHz) or channel 9 (8.0 GHz). Finally the scheme that rides on top — Apple Nearby Interaction, CCC Digital Key, or FiRa — because that decides the frame format and ranging-round structure you must match to capture anything. The honest headline: UWB's ranging is cryptographically protected by the STS, so the real research surface is physical-layer distance manipulation, not key recovery.", + "note": "Work out what the UWB device is before touching the air, there is no capture yet, and UWB has more forks than most protocols. First the silicon: a Qorvo/Decawave DW1000 is the OLD generation (legacy 802.15.4-2011, no STS security) while a DW3000 (DW3110/DW3210) is the modern 802.15.4z part with STS; NXP Trimension (SR040/SR150) and Apple's own U1/U2 are the other major families. Then the PHY: HRP UWB (the one in iPhones, AirTags and car keys) versus the rarer LRP. Then the channel: nearly everything is channel 5 (6.5 GHz) or channel 9 (8.0 GHz). Finally the scheme that rides on top, Apple Nearby Interaction, CCC Digital Key, or FiRa, because that decides the frame format and ranging-round structure you must match to capture anything. The honest headline: UWB's ranging is cryptographically protected by the STS, so the real research surface is physical-layer distance manipulation, not key recovery.", "lookFor": [ - "Chipset / silicon family — Qorvo DW1000 (legacy, no STS) vs DW3000/DW3110/DW3210 (802.15.4z, STS); NXP Trimension SR040/SR150; Apple U1/U2. Read it from the FCC ID, a teardown, or the host SDK. This single fork decides whether STS-protected secure ranging is even in play.", - "PHY: HRP (High Rate Pulse-repetition — phones, AirTags, car keys, the Ghost-Peak-relevant one) vs LRP. They are incompatible at the waveform level, so it sets which radio and config can even hear the link.", - "Channel — almost always channel 5 (6489.6 MHz) or channel 9 (7987.2 MHz). You must know it in advance; a sniffer cannot scan UWB the way it scans 2.4 GHz.", - "Scheme / application protocol — Apple Nearby Interaction, CCC Digital Key (car access), or FiRa (RTLS). Often inferred from the product and from a companion BLE/NFC channel that bootstraps the UWB session (UWB ranging is usually negotiated and keyed over a separate BLE or NFC link first).", - "How the ranging session is set up: UWB rarely runs alone. Apple Nearby Interaction and CCC both bootstrap over Bluetooth LE (and CCC also over NFC) to exchange the session keys and STS parameters — so the BLE/NFC side is often the softer, more observable surface (see the BLE and RFID/NFC wayfinders).", - "Cross-reference known weaknesses: the Ghost Peak distance-reduction attack on HRP 802.15.4z (Apple U1 interoperating with NXP/Qorvo) and the broader academic relay / distance-reduction / preamble-injection literature — these are physical-layer ranging attacks, not key breaks." + "Chipset / silicon family, Qorvo DW1000 (legacy, no STS) vs DW3000/DW3110/DW3210 (802.15.4z, STS); NXP Trimension SR040/SR150; Apple U1/U2. Read it from the FCC ID, a teardown, or the host SDK. This single fork decides whether STS-protected secure ranging is even in play.", + "PHY: HRP (High Rate Pulse-repetition, phones, AirTags, car keys, the Ghost-Peak-relevant one) vs LRP. They are incompatible at the waveform level, so it sets which radio and config can even hear the link.", + "Channel, almost always channel 5 (6489.6 MHz) or channel 9 (7987.2 MHz). You must know it in advance; a sniffer cannot scan UWB the way it scans 2.4 GHz.", + "Scheme / application protocol, Apple Nearby Interaction, CCC Digital Key (car access), or FiRa (RTLS). Often inferred from the product and from a companion BLE/NFC channel that bootstraps the UWB session (UWB ranging is usually negotiated and keyed over a separate BLE or NFC link first).", + "How the ranging session is set up: UWB rarely runs alone. Apple Nearby Interaction and CCC both bootstrap over Bluetooth LE (and CCC also over NFC) to exchange the session keys and STS parameters, so the BLE/NFC side is often the softer, more observable surface (see the BLE and RFID/NFC wayfinders).", + "Cross-reference known weaknesses: the Ghost Peak distance-reduction attack on HRP 802.15.4z (Apple U1 interoperating with NXP/Qorvo) and the broader academic relay / distance-reduction / preamble-injection literature, these are physical-layer ranging attacks, not key breaks." ] }, "SP": { - "note": "Be honest: you cannot meaningfully 'see' UWB on a normal waterfall, and no SDR in this kit can capture it. Impulse-radio UWB transmits extremely short sub-nanosecond pulses spread across >500 MHz of bandwidth, intermittently and at very low power spectral density — by design it looks like a faint rise in the noise floor, not a peak you can point at. Two things rule the common SDRs out — frequency and bandwidth. UWB lives at channel 5 (6.5 GHz) and channel 9 (8.0 GHz), both ABOVE the 6 GHz ceiling of a HackRF, bladeRF, USRP B210 or SignalSDR Pro (and far above the RTL-SDR’s 1.766 GHz); and a UWB channel is >500 MHz wide, where those radios offer only ~20–122 MHz — so even tuned to the edge one would see a thin slice, never the pulse, and could not demodulate the impulse waveform. The only SDRs that get close are lab-grade: a USRP X410 reaches 7.2 GHz with 400 MHz of bandwidth — enough to sit on channel 5 — but it still falls short of the full >500 MHz channel, barely reaches channel 9, costs roughly US$10k+, and demodulating the impulse waveform in software is research-grade (academic SDR-UWB receivers exist; there is no turnkey tool). So in practice there is no SDR survey step here the way there is for BLE or Wi-Fi: you confirm and capture UWB with a real transceiver that already knows the channel — the DW3000 dev boards at the Capture step, which despread the pulses and frame the packet in silicon — or, just to confirm energy, a >500 MHz real-time spectrum analyser/scope.", + "note": "Be honest: you cannot meaningfully 'see' UWB on a normal waterfall, and no SDR in this kit can capture it. Impulse-radio UWB transmits extremely short sub-nanosecond pulses spread across >500 MHz of bandwidth, intermittently and at very low power spectral density, by design it looks like a faint rise in the noise floor, not a peak you can point at. Two things rule the common SDRs out, frequency and bandwidth. UWB lives at channel 5 (6.5 GHz) and channel 9 (8.0 GHz), both ABOVE the 6 GHz ceiling of a HackRF, bladeRF, USRP B210 or SignalSDR Pro (and far above the RTL-SDR’s 1.766 GHz); and a UWB channel is >500 MHz wide, where those radios offer only ~20 to 122 MHz, so even tuned to the edge one would see a thin slice, never the pulse, and could not demodulate the impulse waveform. The only SDRs that get close are lab-grade: a USRP X410 reaches 7.2 GHz with 400 MHz of bandwidth, enough to sit on channel 5, but it still falls short of the full >500 MHz channel, barely reaches channel 9, costs roughly US$10k+, and demodulating the impulse waveform in software is research-grade (academic SDR-UWB receivers exist; there is no turnkey tool). So in practice there is no SDR survey step here the way there is for BLE or Wi-Fi: you confirm and capture UWB with a real transceiver that already knows the channel, the DW3000 dev boards at the Capture step, which despread the pulses and frame the packet in silicon, or, just to confirm energy, a >500 MHz real-time spectrum analyser/scope.", "tools": [] }, "PHY": { - "note": "No commodity SDR demodulates impulse-radio UWB, and there is no separate I/Q-then-frame split as with other protocols: the DW3000-class transceiver despreads the pulses against the known channel/preamble (and, for secure ranging, the STS) and frames the 802.15.4z packet in hardware. So the PHY and the framing happen together on a real UWB chip at the Capture step — you drive the transceiver, you do not stare at a waveform. The catch is that you must already know the PHY parameters (channel, preamble code, PRF, data rate, STS mode/length) to make the radio lock on; those come from the Identify step, not from scanning." + "note": "No commodity SDR demodulates impulse-radio UWB, and there is no separate I/Q-then-frame split as with other protocols: the DW3000-class transceiver despreads the pulses against the known channel/preamble (and, for secure ranging, the STS) and frames the 802.15.4z packet in hardware. So the PHY and the framing happen together on a real UWB chip at the Capture step, you drive the transceiver, you do not stare at a waveform. The catch is that you must already know the PHY parameters (channel, preamble code, PRF, data rate, STS mode/length) to make the radio lock on; those come from the Identify step, not from scanning." }, "LL": { - "note": "Capture UWB frames with a real UWB transceiver, because nothing else can. The open path is the SEEMOO uwb-sniffer: firmware for a Qorvo DWM3000EVB driven by a host MCU (a NUCLEO-F429ZI in the reference build) that pulls 802.15.4z frames off the air and forwards them to Wireshark over a sensniff pipe with picosecond-accurate timestamps. The honest catch — true of ALL UWB sniffing — is that you must configure the radio with the link's PHY parameters (channel, preamble code, data rate, STS mode/length) in advance; UWB cannot be blind-scanned, so the Identify step's homework is mandatory. The most capable off-the-shelf alternative is the Forthink sniffer software + Wireshark plugin, but it depends on Forthink's COMMERCIAL UWB dongle (closed hardware) — flagged, not endorsed. Either way you can also bring up a controllable DW3000 peer (Makerfabs board, or the foldedtoad/dwm3000 driver) to generate and log known ranging exchanges. None of this defeats the STS; it captures the frames you can already decode.", + "note": "Capture UWB frames with a real UWB transceiver, because nothing else can. The open path is the SEEMOO uwb-sniffer: firmware for a Qorvo DWM3000EVB driven by a host MCU (a NUCLEO-F429ZI in the reference build) that pulls 802.15.4z frames off the air and forwards them to Wireshark over a sensniff pipe with picosecond-accurate timestamps. The honest catch, true of ALL UWB sniffing, is that you must configure the radio with the link's PHY parameters (channel, preamble code, data rate, STS mode/length) in advance; UWB cannot be blind-scanned, so the Identify step's homework is mandatory. The most capable off-the-shelf alternative is the Forthink sniffer software + Wireshark plugin, but it depends on Forthink's COMMERCIAL UWB dongle (closed hardware), flagged, not endorsed. Either way you can also bring up a controllable DW3000 peer (Makerfabs board, or the foldedtoad/dwm3000 driver) to generate and log known ranging exchanges. None of this defeats the STS; it captures the frames you can already decode.", "decoder": "wireshark", "tools": [ - { "tool": "seemoo-uwb-sniffer", "role": "Open UWB sniffer", "why": "The reference open-source way to capture live 802.15.4z UWB frames: DWM3000EVB firmware that streams to Wireshark over a sensniff pipe with the DW3000's 15.65 ps timestamp accuracy — the instrument used in the Ghost Peak research line.", "caveat": "You must know the link's channel, preamble code, data rate and STS mode/length in advance — UWB cannot be blind-scanned — and it forwards malformed frames too, so check the Wireshark output. It does NOT break the STS.", "deps": ["dwm3000evb"], "needs": "A Qorvo DWM3000EVB plus a host MCU to drive it (a NUCLEO-F429ZI in the reference build; an nRF52840 with code changes), and the PHY parameters recovered at the Identify step." }, - { "tool": "forthink-uwb-sniffer", "role": "Commercial-dongle sniffer", "why": "The most capable off-the-shelf capture path: open host software + a Wireshark plugin that decode CCC, FiRa and 802.15.4a/z, including Apple Car-Key and AirTag/Nearby-Interaction (FiRa) parameters.", "caveat": "FLAGGED — the software is open but it requires Forthink's COMMERCIAL UWB-Dongle-Sniffer (closed hardware, a purchased FT4222H dongle), not open hardware. Observes frames; does not defeat STS-protected ranging integrity.", "deps": ["forthink-uwb-dongle"], "needs": "A purchased Forthink UWB-Dongle-Sniffer; the dongle is the radio (there is no open hardware for it)." }, - { "tool": "dwm3000-dwt-driver", "role": "Controllable DW3000 peer / ranging log", "why": "Bring up a real DW3000 board with Qorvo's dwt_uwb_driver (the foldedtoad Zephyr/Arduino port) to set the 802.15.4z PHY (channel, preamble, PRF, STS mode) and run/log two-way-ranging exchanges — the dev-board way to capture and characterise a scheme's ranging behaviour when you control one end.", "caveat": "A development driver, not a passive sniffer: it captures the exchanges it participates in, not arbitrary third-party links.", "deps": ["dwm3000evb", "makerfabs-esp32-uwb-dw3000"] } + { "tool": "seemoo-uwb-sniffer", "role": "Open UWB sniffer", "why": "The reference open-source way to capture live 802.15.4z UWB frames: DWM3000EVB firmware that streams to Wireshark over a sensniff pipe with the DW3000's 15.65 ps timestamp accuracy, the instrument used in the Ghost Peak research line.", "caveat": "You must know the link's channel, preamble code, data rate and STS mode/length in advance, UWB cannot be blind-scanned, and it forwards malformed frames too, so check the Wireshark output. It does NOT break the STS.", "deps": ["dwm3000evb"], "needs": "A Qorvo DWM3000EVB plus a host MCU to drive it (a NUCLEO-F429ZI in the reference build; an nRF52840 with code changes), and the PHY parameters recovered at the Identify step." }, + { "tool": "forthink-uwb-sniffer", "role": "Commercial-dongle sniffer", "why": "The most capable off-the-shelf capture path: open host software + a Wireshark plugin that decode CCC, FiRa and 802.15.4a/z, including Apple Car-Key and AirTag/Nearby-Interaction (FiRa) parameters.", "caveat": "FLAGGED, the software is open but it requires Forthink's COMMERCIAL UWB-Dongle-Sniffer (closed hardware, a purchased FT4222H dongle), not open hardware. Observes frames; does not defeat STS-protected ranging integrity.", "deps": ["forthink-uwb-dongle"], "needs": "A purchased Forthink UWB-Dongle-Sniffer; the dongle is the radio (there is no open hardware for it)." }, + { "tool": "dwm3000-dwt-driver", "role": "Controllable DW3000 peer / ranging log", "why": "Bring up a real DW3000 board with Qorvo's dwt_uwb_driver (the foldedtoad Zephyr/Arduino port) to set the 802.15.4z PHY (channel, preamble, PRF, STS mode) and run/log two-way-ranging exchanges, the dev-board way to capture and characterise a scheme's ranging behaviour when you control one end.", "caveat": "A development driver, not a passive sniffer: it captures the exchanges it participates in, not arbitrary third-party links.", "deps": ["dwm3000evb", "makerfabs-esp32-uwb-dw3000"] } ] }, "CR": { - "note": "Reset the expectation here: there is no key to crack, and that is the whole point of 802.15.4z. The STS (Scrambled Timestamp Sequence) is an AES-keyed pseudo-random sequence of pulses that the two ranging peers share — the receiver correlates the incoming impulse against the STS it expects, and only an STS-authenticated arrival time is trusted as a distance measurement. So an attacker who does not hold the STS key cannot forge or replay a legitimate ranging pulse, and the BLE/Wi-Fi-style attack of recovering a session key offline does not exist for the ranging itself. The STS key, where it is exchanged, is set up over the separate bootstrap channel (BLE for Apple Nearby Interaction / CCC, NFC for some CCC flows) — so any crypto weakness lives in THAT handshake, not in the UWB pulses, and is assessed in the BLE or RFID/NFC wayfinder. The genuine UWB research surface is not the key but the physics: can the time-of-flight measurement be manipulated at the physical layer (early detection, preamble/pulse injection) even without the key? That is the Attack step. There is no open key-cracking tool here because there is no key-cracking attack to run." + "note": "Reset the expectation here: there is no key to crack, and that is the whole point of 802.15.4z. The STS (Scrambled Timestamp Sequence) is an AES-keyed pseudo-random sequence of pulses that the two ranging peers share, the receiver correlates the incoming impulse against the STS it expects, and only an STS-authenticated arrival time is trusted as a distance measurement. So an attacker who does not hold the STS key cannot forge or replay a legitimate ranging pulse, and the BLE/Wi-Fi-style attack of recovering a session key offline does not exist for the ranging itself. The STS key, where it is exchanged, is set up over the separate bootstrap channel (BLE for Apple Nearby Interaction / CCC, NFC for some CCC flows), so any crypto weakness lives in THAT handshake, not in the UWB pulses, and is assessed in the BLE or RFID/NFC wayfinder. The genuine UWB research surface is not the key but the physics: can the time-of-flight measurement be manipulated at the physical layer (early detection, preamble/pulse injection) even without the key? That is the Attack step. There is no open key-cracking tool here because there is no key-cracking attack to run." }, "AT": { - "note": "The real UWB attack is PHYSICAL-LAYER distance manipulation, not takeover — and it is academic, specialist, and AUTHORISED-only. Because distance is derived from pulse time-of-flight, the research attacks try to make the receiver register an EARLIER arrival than the true one, shortening the measured distance, WITHOUT needing the STS key: 'early-detect / late-commit' and preamble-injection attacks on the HRP 802.15.4z waveform, and relay attacks that shuttle the ranging exchange between a distant car and key. The landmark public result is Ghost Peak (Leu, Camurati, Heinrich et al., USENIX Security 2022): a practical distance-reduction attack on HRP UWB against Apple U1 inter-operating with NXP/Qorvo chips, reducing 12 m to 0 m with a ~4% per-attempt success rate, using only a ~$65 off-the-shelf device (a DWM3000EVB driven by an nRF52DK) and NO cryptographic material. Be honest about the tooling: there is NO push-button, ready-to-run open attack tool for this. The published work uses custom DW3000 firmware and bespoke setups that are not packaged as a product; reproducing it means engineering against a DW3000 board, not downloading an exploit. We cite the research and provide the controllable hardware peer — we do not hand you a weapon that does not openly exist.", + "note": "The real UWB attack is PHYSICAL-LAYER distance manipulation, not takeover, and it is academic, specialist, and AUTHORISED-only. Because distance is derived from pulse time-of-flight, the research attacks try to make the receiver register an EARLIER arrival than the true one, shortening the measured distance, WITHOUT needing the STS key: 'early-detect / late-commit' and preamble-injection attacks on the HRP 802.15.4z waveform, and relay attacks that shuttle the ranging exchange between a distant car and key. The landmark public result is Ghost Peak (Leu, Camurati, Heinrich et al., USENIX Security 2022): a practical distance-reduction attack on HRP UWB against Apple U1 inter-operating with NXP/Qorvo chips, reducing 12 m to 0 m with a ~4% per-attempt success rate, using only a ~$65 off-the-shelf device (a DWM3000EVB driven by an nRF52DK) and NO cryptographic material. Be honest about the tooling: there is NO push-button, ready-to-run open attack tool for this. The published work uses custom DW3000 firmware and bespoke setups that are not packaged as a product; reproducing it means engineering against a DW3000 board, not downloading an exploit. We cite the research and provide the controllable hardware peer, we do not hand you a weapon that does not openly exist.", "tools": [ - { "tool": "dwm3000-dwt-driver", "role": "Controllable UWB peer (research)", "why": "Authorised distance-manipulation and relay research is built on a programmable DW3000 board: this open driver/firmware lets you control the 802.15.4z PHY and timing on a real transceiver — the substrate the academic attacks (e.g. the Ghost Peak platform) are engineered on. There is no off-the-shelf attack binary; the radio you can program is the honest starting point.", "caveat": "AUTHORISED testing only. This is a development peer, NOT a packaged distance-reduction exploit — Ghost Peak-style attacks require custom firmware and RF engineering that are not openly released as a tool. Cite the research; do not expect a one-click attack.", "deps": ["dwm3000evb", "makerfabs-esp32-uwb-dw3000"], "needs": "A programmable DW3000 board (DWM3000EVB or Makerfabs ESP32-UWB) and the link's PHY parameters from the Identify step. Reference: Ghost Peak — securepositioning.ch/ghost-peak (arXiv 2111.05313, USENIX Security 2022) — and the broader 802.15.4z relay / preamble-injection literature. NO open turnkey tool exists." } + { "tool": "dwm3000-dwt-driver", "role": "Controllable UWB peer (research)", "why": "Authorised distance-manipulation and relay research is built on a programmable DW3000 board: this open driver/firmware lets you control the 802.15.4z PHY and timing on a real transceiver, the substrate the academic attacks (e.g. the Ghost Peak platform) are engineered on. There is no off-the-shelf attack binary; the radio you can program is the honest starting point.", "caveat": "AUTHORISED testing only. This is a development peer, NOT a packaged distance-reduction exploit, Ghost Peak-style attacks require custom firmware and RF engineering that are not openly released as a tool. Cite the research; do not expect a one-click attack.", "deps": ["dwm3000evb", "makerfabs-esp32-uwb-dw3000"], "needs": "A programmable DW3000 board (DWM3000EVB or Makerfabs ESP32-UWB) and the link's PHY parameters from the Identify step. Reference: Ghost Peak, securepositioning.ch/ghost-peak (arXiv 2111.05313, USENIX Security 2022), and the broader 802.15.4z relay / preamble-injection literature. NO open turnkey tool exists." } ] }, "AP": { - "note": "Above the pulses, UWB's 'application' is the ranging/positioning decision and what trusts it — and that is where the impact lands, even though the link itself is hard to break. A UWB measurement feeds a security gate: a car's CCC Digital Key unlocks/starts only when the phone or key fob is ranged within a few tens of centimetres; Apple Nearby Interaction surfaces precise direction/distance to apps; an RTLS makes access or safety decisions on position. The assessment question is whether those consumers correctly enforce the SECURE-RANGING assumptions — do they require an STS-authenticated measurement (not a legacy or non-secure one), do they bound the acceptable distance tightly, do they reject implausible jumps, and do they fail safe if ranging is lost or manipulated? Because the proven attacks shorten distance at the physical layer, the application-layer test is essentially: if an attacker did reduce the measured distance (Ghost Peak-style), would the car unlock / the door open / the payment proceed — and is the proximity check the only thing standing between the attacker and the asset? This is assessed in the victim system's logic (and in the BLE/NFC bootstrap that keys the session), since UWB ranging exposes no interactive protocol surface of its own to probe." + "note": "Above the pulses, UWB's 'application' is the ranging/positioning decision and what trusts it, and that is where the impact lands, even though the link itself is hard to break. A UWB measurement feeds a security gate: a car's CCC Digital Key unlocks/starts only when the phone or key fob is ranged within a few tens of centimetres; Apple Nearby Interaction surfaces precise direction/distance to apps; an RTLS makes access or safety decisions on position. The assessment question is whether those consumers correctly enforce the SECURE-RANGING assumptions, do they require an STS-authenticated measurement (not a legacy or non-secure one), do they bound the acceptable distance tightly, do they reject implausible jumps, and do they fail safe if ranging is lost or manipulated? Because the proven attacks shorten distance at the physical layer, the application-layer test is essentially: if an attacker did reduce the measured distance (Ghost Peak-style), would the car unlock / the door open / the payment proceed, and is the proximity check the only thing standing between the attacker and the asset? This is assessed in the victim system's logic (and in the BLE/NFC bootstrap that keys the session), since UWB ranging exposes no interactive protocol surface of its own to probe." } } }; diff --git a/src/data/toolchains/zigbee.js b/src/data/toolchains/zigbee.js index 0cd1bdb..f75a272 100644 --- a/src/data/toolchains/zigbee.js +++ b/src/data/toolchains/zigbee.js @@ -1,72 +1,72 @@ export default { "status": "complete", "facts": [ - { "k": "Band", "v": "2.4 GHz (2.405–2.480 GHz ISM) — primary · sub-GHz 868 MHz (Europe) / 902–928 MHz (Americas)" }, - { "k": "Channels", "v": "2.4 GHz: 16 channels, 11–26, spaced 5 MHz · sub-GHz: ch 0 @ 868 MHz and ch 1–10 @ 915 MHz band" }, - { "k": "PHY / Modulation", "v": "IEEE 802.15.4 — 2.4 GHz uses O-QPSK with DSSS, 250 kbps; sub-GHz uses BPSK/O-QPSK at lower rates" }, + { "k": "Band", "v": "2.4 GHz (2.405 to 2.480 GHz ISM), primary · sub-GHz 868 MHz (Europe) / 902 to 928 MHz (Americas)" }, + { "k": "Channels", "v": "2.4 GHz: 16 channels, 11 to 26, spaced 5 MHz · sub-GHz: ch 0 @ 868 MHz and ch 1 to 10 @ 915 MHz band" }, + { "k": "PHY / Modulation", "v": "IEEE 802.15.4, 2.4 GHz uses O-QPSK with DSSS, 250 kbps; sub-GHz uses BPSK/O-QPSK at lower rates" }, { "k": "Stack", "v": "802.15.4 MAC/PHY → Zigbee NWK (mesh routing) → APS (application support) → ZCL/ZDO. Roles: Coordinator, Router, End Device" }, { "k": "Security", "v": "AES-128-CCM* at NWK and APS layers. A network key shared by the whole PAN; a Trust Center link key gates joining. Default well-known TC link key 'ZigBeeAlliance09' (hex 5A6967426565416C6C69616E63653039)" }, - { "k": "Range", "v": "~10–100 m per hop indoors; the mesh extends reach by routing through mains-powered Routers" } + { "k": "Range", "v": "~10 to 100 m per hop indoors; the mesh extends reach by routing through mains-powered Routers" } ], "reference": null, "layers": { "IG": { - "note": "Identify the device and its Zigbee profile before any RF work — no capture yet. The goal is to know what you are dealing with: which radio SoC it runs, whether it is a Coordinator (the hub/Trust Center), a Router or an End Device, which channel and PAN it lives on, and how it secures joining. Much of this is readable from the FCC ID and a teardown, and the rest falls out the moment you watch a join.", + "note": "Identify the device and its Zigbee profile before any RF work, no capture yet. The goal is to know what you are dealing with: which radio SoC it runs, whether it is a Coordinator (the hub/Trust Center), a Router or an End Device, which channel and PAN it lives on, and how it secures joining. Much of this is readable from the FCC ID and a teardown, and the rest falls out the moment you watch a join.", "lookFor": [ - "Chipset / SoC and stack (FCC ID, teardown, module markings — Silicon Labs EFR32/EM35x, TI CC2530/CC2538/CC1352, NXP JN51xx, Espressif ESP32-C6) — cross-reference known Zigbee/802.15.4 CVEs and vendor stack advisories.", - "Role in the mesh: Coordinator (also the Trust Center that hands out keys), Router (mains-powered, relays) or End Device (often sleepy/battery) — sets what you will see on air and what to target.", - "Channel and PAN: the 802.15.4 channel (11–26 at 2.4 GHz), the 16-bit PAN ID and 64-bit extended PAN ID, and the network's short/extended addresses.", + "Chipset / SoC and stack (FCC ID, teardown, module markings, Silicon Labs EFR32/EM35x, TI CC2530/CC2538/CC1352, NXP JN51xx, Espressif ESP32-C6), cross-reference known Zigbee/802.15.4 CVEs and vendor stack advisories.", + "Role in the mesh: Coordinator (also the Trust Center that hands out keys), Router (mains-powered, relays) or End Device (often sleepy/battery), sets what you will see on air and what to target.", + "Channel and PAN: the 802.15.4 channel (11 to 26 at 2.4 GHz), the 16-bit PAN ID and 64-bit extended PAN ID, and the network's short/extended addresses.", "Join / security model: centralized (a Trust Center using a link key) vs distributed; whether it relies on the well-known default Trust Center link key 'ZigBeeAlliance09', a per-device install code, or Zigbee 3.0 install-code-only joining.", "Profile and application: Zigbee 3.0 / Home Automation / Light Link, the device's clusters (on/off, level, lock, thermostat) and which are reachable.", "Identifiers: manufacturer/model strings reported over ZCL, the EUI-64, and whether the device leaks them before encryption is in force." ] }, "SP": { - "note": "Before capturing, find which of the 16 channels the network is on. Zigbee at 2.4 GHz pins each PAN to one 2 MHz-wide channel (11–26, every 5 MHz across the band) and stays there — it does not frequency-hop like BLE — so the job is a channel scan, not chasing hops. The fast way is an energy/active scan with the capture radio itself; an SDR waterfall is a coarse cross-check to see which channels are lit (and Wi-Fi overlaps heavily in this band, so expect interference). Channels 15, 20, 25 and 26 sit in the gaps between Wi-Fi channels and are common Zigbee choices.", + "note": "Before capturing, find which of the 16 channels the network is on. Zigbee at 2.4 GHz pins each PAN to one 2 MHz-wide channel (11 to 26, every 5 MHz across the band) and stays there, it does not frequency-hop like BLE, so the job is a channel scan, not chasing hops. The fast way is an energy/active scan with the capture radio itself; an SDR waterfall is a coarse cross-check to see which channels are lit (and Wi-Fi overlaps heavily in this band, so expect interference). Channels 15, 20, 25 and 26 sit in the gaps between Wi-Fi channels and are common Zigbee choices.", "tools": [ - { "tool": "killerbee", "role": "Channel / network scan", "why": "zbstumbler walks the channels transmitting beacon requests and logs the PANs that answer (PAN ID, channel, stack profile) — an active scan that finds the network and its channel fast.", "caveat": "Active: it transmits beacon requests. For a purely passive sweep, energy-scan with the capture radio instead. Runs on its own KillerBee radios (ApiMote / RZUSBstick / nRF52840) — not on the CatSniffer.", "deps": ["apimote", "nrf52840-dongle"] }, - { "tool": "gqrx", "role": "Spectrum / waterfall view", "why": "Coarse cross-check of which channels are lit across the 2.4 GHz band on an SDR — useful to spot activity and judge Wi-Fi overlap before committing to a channel.", "caveat": "Sees energy, not Zigbee frames; can't tell Zigbee from Wi-Fi/BLE by waterfall alone.", "deps": ["hackrf-one", "bladerf-2-micro"] }, - { "tool": "minino", "role": "Pocket scanner", "why": "Electronic Cats ESP32-C6 multitool with native 802.15.4: standalone channel/PAN recon in the field with onboard OLED, GPS and microSD — no laptop needed.", "deps": [] }, - { "tool": "kismet", "role": "Passive channel survey", "why": "Kismet channel-hops the 802.15.4 band and logs every PAN, coordinator and device it hears to pcapng with GPS — a passive survey that, unlike zbstumbler, never sends a beacon request. It drives the widest set of 802.15.4 radios here (CatSniffer v3, nRF52840, CC2531, RZUSBstick), so you survey with whatever board you carry.", "deps": ["catsniffer", "nrf52840-dongle", "cc2531"], "caveat": "Passive only. The CatSniffer Zigbee datasource needs a v3 (v1/v2 can’t capture Zigbee in Kismet) flashed with the RP2040 passthrough + Zigbee firmware, on Kismet git / a 2025-10+ release; it appears as a serial port (specify it manually)." }, - { "tool": "catnip", "role": "Channel activity & topology (cativity)", "why": "catnip's cativity mode channel-hops 802.15.4 (11–26) and draws a live per-channel activity table — so you spot the busy Zigbee channel at a glance — with a fixed-channel mode for detail and a network-topology discovery that maps the coordinator / router / end-device relationships. Runs on the CatSniffer, native to the EC kit.", "deps": ["catsniffer"] } + { "tool": "killerbee", "role": "Channel / network scan", "why": "zbstumbler walks the channels transmitting beacon requests and logs the PANs that answer (PAN ID, channel, stack profile), an active scan that finds the network and its channel fast.", "caveat": "Active: it transmits beacon requests. For a purely passive sweep, energy-scan with the capture radio instead. Runs on its own KillerBee radios (ApiMote / RZUSBstick / nRF52840), not on the CatSniffer.", "deps": ["apimote", "nrf52840-dongle"] }, + { "tool": "gqrx", "role": "Spectrum / waterfall view", "why": "Coarse cross-check of which channels are lit across the 2.4 GHz band on an SDR, useful to spot activity and judge Wi-Fi overlap before committing to a channel.", "caveat": "Sees energy, not Zigbee frames; can't tell Zigbee from Wi-Fi/BLE by waterfall alone.", "deps": ["hackrf-one", "bladerf-2-micro"] }, + { "tool": "minino", "role": "Pocket scanner", "why": "Electronic Cats ESP32-C6 multitool with native 802.15.4: standalone channel/PAN recon in the field with onboard OLED, GPS and microSD, no laptop needed.", "deps": [] }, + { "tool": "kismet", "role": "Passive channel survey", "why": "Kismet channel-hops the 802.15.4 band and logs every PAN, coordinator and device it hears to pcapng with GPS, a passive survey that, unlike zbstumbler, never sends a beacon request. It drives the widest set of 802.15.4 radios here (CatSniffer v3, nRF52840, CC2531, RZUSBstick), so you survey with whatever board you carry.", "deps": ["catsniffer", "nrf52840-dongle", "cc2531"], "caveat": "Passive only. The CatSniffer Zigbee datasource needs a v3 (v1/v2 can’t capture Zigbee in Kismet) flashed with the RP2040 passthrough + Zigbee firmware, on Kismet git / a 2025-10+ release; it appears as a serial port (specify it manually)." }, + { "tool": "catnip", "role": "Channel activity & topology (cativity)", "why": "catnip's cativity mode channel-hops 802.15.4 (11 to 26) and draws a live per-channel activity table, so you spot the busy Zigbee channel at a glance, with a fixed-channel mode for detail and a network-topology discovery that maps the coordinator / router / end-device relationships. Runs on the CatSniffer, native to the EC kit.", "deps": ["catsniffer"] } ] }, "PHY": { - "note": "No standalone Zigbee demodulator in this kit. The capture radios demodulate the 802.15.4 O-QPSK/DSSS waveform (PHY) and frame the MAC packets (LL) together on their own 802.15.4 chipset, so PHY and Capture live as one step. A wide-band SDR can show the spectrum, but decoding live O-QPSK/DSSS in software is impractical — use a real 802.15.4 radio for capture." + "note": "No standalone Zigbee demodulator in this kit. The capture radios demodulate the 802.15.4 O-QPSK/DSSS waveform (PHY) and frame the MAC packets (LL) together on their own 802.15.4 chipset, so PHY and Capture live as one step. A wide-band SDR can show the spectrum, but decoding live O-QPSK/DSSS in software is impractical, use a real 802.15.4 radio for capture." }, "LL": { - "note": "Capture and decode 802.15.4 / Zigbee frames. Park an 802.15.4 radio on the target's channel and it pulls beacons, MAC frames, the join exchange and the encrypted NWK/APS payloads off the air into a PCAP. Pick a capture tool by the radio you have; each feeds Wireshark, whose Zigbee dissector decodes NWK and APS (and will decrypt the upper layers once you supply the network key). On a CatSniffer the sniffer software is catnip (Electronic Cats' CatSniffer-Tools, which bundles pycatsniffer) — it streams 802.15.4/Zigbee frames into Wireshark over its extcap. Crucially, capture a device joining — that is where the network key is transported and where the whole network opens up.", + "note": "Capture and decode 802.15.4 / Zigbee frames. Park an 802.15.4 radio on the target's channel and it pulls beacons, MAC frames, the join exchange and the encrypted NWK/APS payloads off the air into a PCAP. Pick a capture tool by the radio you have; each feeds Wireshark, whose Zigbee dissector decodes NWK and APS (and will decrypt the upper layers once you supply the network key). On a CatSniffer the sniffer software is catnip (Electronic Cats' CatSniffer-Tools, which bundles pycatsniffer), it streams 802.15.4/Zigbee frames into Wireshark over its extcap. Crucially, capture a device joining, that is where the network key is transported and where the whole network opens up.", "decoder": "wireshark", "tools": [ - { "tool": "killerbee", "role": "Primary capture", "why": "zbdump writes a PCAP and zbwireshark pipes frames live into Wireshark, on whichever 802.15.4 radio KillerBee supports — the standard capture path for Zigbee assessment.", "caveat": "Runs on KillerBee's own radios (ApiMote / RZUSBstick / nRF52840), not the CatSniffer.", "deps": ["apimote", "nrf52840-dongle"] }, - { "tool": "catnip", "role": "CatSniffer capture", "why": "Electronic Cats' CatSniffer-Tools (catnip, which bundles pycatsniffer) drives the CC1352-based CatSniffer as an 802.15.4/Zigbee sniffer and streams frames into Wireshark via its extcap — the native capture path for a CatSniffer.", "deps": ["catsniffer"] }, - { "tool": "nrf-sniffer-802154", "role": "Turnkey capture", "why": "Nordic's firmware + Wireshark extcap plugin captures raw 2.4 GHz 802.15.4 straight into Wireshark — the easiest, best-documented first capture on cheap nRF52840 hardware.", "deps": ["nrf52840-dongle"] }, - { "tool": "whsniff", "role": "CC2531 capture", "why": "Bridges a TI CC2531 USB dongle to Wireshark for live 2.4 GHz 802.15.4 capture — a cheap, simple capture path when you have a CC2531.", "caveat": "CC2531 is 2.4 GHz only and capture-only (no injection).", "deps": ["cc2531"] }, - { "tool": "minino", "role": "Pocket sniffer", "why": "Standalone ESP32-C6 802.15.4 sniffer that writes Wireshark-compatible captures to microSD — capture in the field with no host PC.", "deps": [] }, - { "tool": "whad", "role": "Multi-protocol sniff/inject", "why": "WHAD drives an nRF52840 (its Butterfly firmware) or an APIMote as an 802.15.4/Zigbee sniffer from one Python framework, exporting PCAP/Scapy — and on a transmit-capable radio it can forge and inject frames too. The same toolchain you use for BLE and Thread.", "deps": ["nrf52840-dongle", "apimote"] }, - { "tool": "kismet", "role": "Multi-radio capture", "why": "Captures raw 802.15.4/Zigbee frames to pcapng (open them in Wireshark) while it surveys, and supports more 802.15.4 radios than anything else here — a dedicated CatSniffer v3 Zigbee datasource (channels 12–26), plus nRF52840, CC2531, RZUSBstick and NXP KW41Z — so one tool covers most boards you’ll meet.", "deps": ["catsniffer", "nrf52840-dongle", "cc2531"], "caveat": "CatSniffer must be a v3 with the RP2040 serial-passthrough + Zigbee capture firmware (v1/v2 can’t); needs Kismet git or a 2025-10+ release, and the source is specified manually as a serial port." } + { "tool": "killerbee", "role": "Primary capture", "why": "zbdump writes a PCAP and zbwireshark pipes frames live into Wireshark, on whichever 802.15.4 radio KillerBee supports, the standard capture path for Zigbee assessment.", "caveat": "Runs on KillerBee's own radios (ApiMote / RZUSBstick / nRF52840), not the CatSniffer.", "deps": ["apimote", "nrf52840-dongle"] }, + { "tool": "catnip", "role": "CatSniffer capture", "why": "Electronic Cats' CatSniffer-Tools (catnip, which bundles pycatsniffer) drives the CC1352-based CatSniffer as an 802.15.4/Zigbee sniffer and streams frames into Wireshark via its extcap, the native capture path for a CatSniffer.", "deps": ["catsniffer"] }, + { "tool": "nrf-sniffer-802154", "role": "Turnkey capture", "why": "Nordic's firmware + Wireshark extcap plugin captures raw 2.4 GHz 802.15.4 straight into Wireshark, the easiest, best-documented first capture on cheap nRF52840 hardware.", "deps": ["nrf52840-dongle"] }, + { "tool": "whsniff", "role": "CC2531 capture", "why": "Bridges a TI CC2531 USB dongle to Wireshark for live 2.4 GHz 802.15.4 capture, a cheap, simple capture path when you have a CC2531.", "caveat": "CC2531 is 2.4 GHz only and capture-only (no injection).", "deps": ["cc2531"] }, + { "tool": "minino", "role": "Pocket sniffer", "why": "Standalone ESP32-C6 802.15.4 sniffer that writes Wireshark-compatible captures to microSD, capture in the field with no host PC.", "deps": [] }, + { "tool": "whad", "role": "Multi-protocol sniff/inject", "why": "WHAD drives an nRF52840 (its Butterfly firmware) or an APIMote as an 802.15.4/Zigbee sniffer from one Python framework, exporting PCAP/Scapy, and on a transmit-capable radio it can forge and inject frames too. The same toolchain you use for BLE and Thread.", "deps": ["nrf52840-dongle", "apimote"] }, + { "tool": "kismet", "role": "Multi-radio capture", "why": "Captures raw 802.15.4/Zigbee frames to pcapng (open them in Wireshark) while it surveys, and supports more 802.15.4 radios than anything else here, a dedicated CatSniffer v3 Zigbee datasource (channels 12 to 26), plus nRF52840, CC2531, RZUSBstick and NXP KW41Z, so one tool covers most boards you’ll meet.", "deps": ["catsniffer", "nrf52840-dongle", "cc2531"], "caveat": "CatSniffer must be a v3 with the RP2040 serial-passthrough + Zigbee capture firmware (v1/v2 can’t); needs Kismet git or a 2025-10+ release, and the source is specified manually as a serial port." } ] }, "CR": { - "note": "Assess the join security and recover the network key where it was transported weakly. Zigbee encrypts NWK and APS with AES-128-CCM*, so the whole capture hinges on the network key — and the classic weakness is how that key reaches a joining device. In a centralized network the Trust Center sends the network key in an APS Transport-Key during the join; if it is protected only by the well-known default Trust Center link key 'ZigBeeAlliance09' (or sent in the clear on older devices), anyone who captured the join can recover it. So the attack is: capture a device joining, then extract the key. Once you have the network key, load it into Wireshark and the dissector decrypts the mesh.", + "note": "Assess the join security and recover the network key where it was transported weakly. Zigbee encrypts NWK and APS with AES-128-CCM*, so the whole capture hinges on the network key, and the classic weakness is how that key reaches a joining device. In a centralized network the Trust Center sends the network key in an APS Transport-Key during the join; if it is protected only by the well-known default Trust Center link key 'ZigBeeAlliance09' (or sent in the clear on older devices), anyone who captured the join can recover it. So the attack is: capture a device joining, then extract the key. Once you have the network key, load it into Wireshark and the dissector decrypts the mesh.", "tools": [ - { "tool": "zbdsniff", "role": "Network-key extraction", "why": "Scans a join capture for the APS Transport-Key and recovers the Zigbee network key — decrypting it under the well-known default Trust Center link key 'ZigBeeAlliance09' (or reading it directly when sent in the clear).", "caveat": "Only works when the key was transported under the default TC link key or unencrypted; a per-device install code defeats it.", "deps": ["wireshark"], "needs": "A PCAP that contains a device joining the network (the APS Transport-Key frame). Capture the join at the Capture step (KillerBee / catnip on a CatSniffer / nRF Sniffer / whsniff), save the PCAP from Wireshark, then run zbdsniff over that file. To force a fresh join, power-cycle or re-pair the target device while capturing." }, - { "tool": "wireshark", "role": "Decrypt with the key", "why": "Once you have the network key, paste it into Wireshark's Zigbee protocol preferences (and the well-known TC link key 'ZigBeeAlliance09') and the dissector decrypts NWK/APS in the capture — turning ciphertext into readable cluster commands.", "deps": [], "needs": "The network key recovered by zbdsniff (or a key you already hold). Add it under Edit → Preferences → Protocols → ZigBee, then reload the capture." } + { "tool": "zbdsniff", "role": "Network-key extraction", "why": "Scans a join capture for the APS Transport-Key and recovers the Zigbee network key, decrypting it under the well-known default Trust Center link key 'ZigBeeAlliance09' (or reading it directly when sent in the clear).", "caveat": "Only works when the key was transported under the default TC link key or unencrypted; a per-device install code defeats it.", "deps": ["wireshark"], "needs": "A PCAP that contains a device joining the network (the APS Transport-Key frame). Capture the join at the Capture step (KillerBee / catnip on a CatSniffer / nRF Sniffer / whsniff), save the PCAP from Wireshark, then run zbdsniff over that file. To force a fresh join, power-cycle or re-pair the target device while capturing." }, + { "tool": "wireshark", "role": "Decrypt with the key", "why": "Once you have the network key, paste it into Wireshark's Zigbee protocol preferences (and the well-known TC link key 'ZigBeeAlliance09') and the dissector decrypts NWK/APS in the capture, turning ciphertext into readable cluster commands.", "deps": [], "needs": "The network key recovered by zbdsniff (or a key you already hold). Add it under Edit → Preferences → Protocols → ZigBee, then reload the capture." } ] }, "AT": { "note": "Actively take over or disrupt the mesh. Pick the technique; each names the 802.15.4 radio it runs on, and replay/injection need a radio that can transmit (the ApiMote, and the CatSniffer via catnip, can; capture-only dongles cannot). With the network key in hand you can forge and inject frames; even without it, captured encrypted commands can sometimes be replayed wholesale, and a forced leave/rejoin can be abused to re-capture a join (and thus the key).", "tools": [ - { "tool": "killerbee", "role": "Replay & inject", "why": "zbreplay re-transmits frames captured earlier (e.g. an on/off or unlock command) back into the network, and the framework's tools forge frames once you hold the network key — the practical replay/injection path.", "caveat": "Needs a transmit-capable KillerBee 802.15.4 radio (ApiMote); capture-only dongles can't inject.", "deps": ["apimote"] }, - { "tool": "killerbee", "role": "Join / rejoin abuse", "why": "Force a target to leave and rejoin so a fresh join (and its key transport) hits the air again — KillerBee's framework drives the disruptive scans/floods that provoke a rejoin, which you then capture for key extraction at the Break-crypto step.", "caveat": "Disruptive and noisy; transmits into the live network.", "deps": ["apimote"] }, + { "tool": "killerbee", "role": "Replay & inject", "why": "zbreplay re-transmits frames captured earlier (e.g. an on/off or unlock command) back into the network, and the framework's tools forge frames once you hold the network key, the practical replay/injection path.", "caveat": "Needs a transmit-capable KillerBee 802.15.4 radio (ApiMote); capture-only dongles can't inject.", "deps": ["apimote"] }, + { "tool": "killerbee", "role": "Join / rejoin abuse", "why": "Force a target to leave and rejoin so a fresh join (and its key transport) hits the air again, KillerBee's framework drives the disruptive scans/floods that provoke a rejoin, which you then capture for key extraction at the Break-crypto step.", "caveat": "Disruptive and noisy; transmits into the live network.", "deps": ["apimote"] }, { "tool": "catnip", "role": "OTA firmware-update MITM / jamming", "why": "Electronic Cats' CatSniffer OTA PoC drives the CC1352 CatSniffer to sniff a Zigbee OTA firmware update and capture the APS Transport-Key (decrypting the exchange without the default key), then jams the legitimate OTA server to force the client to rejoin a rogue server and accept attacker-supplied firmware. See poc/Poc_Zigbee in github.com/ElectronicCats/CatSniffer (CatSniffer MITM ZigBee OTA Server-Client / CatSniffer Targeting OTA Server).", "caveat": "The jamming/rogue-server stage needs an external jammer alongside the CatSniffer (per the PoC); the sniff/MITM stage runs on the CatSniffer alone.", "deps": ["catsniffer"] }, { "tool": "minino", "role": "Pocket 802.15.4 attacker", "why": "Electronic Cats ESP32-C6 field tool with native 802.15.4 for standalone Zigbee/Thread recon and disruption without a laptop.", "caveat": "2.4 GHz only; field recon/disruption, not the full KillerBee injection suite.", "deps": [] } ] }, "AP": { - "note": "Test what the device trusts above the link — the Zigbee Cluster Library (ZCL) commands a Coordinator would send: toggle a relay, unlock a lock, set a thermostat, read attributes. Once you hold the network key you can craft these as encrypted APS frames and inject them, or join a Trust Center / coordinator stack to the network and drive devices legitimately. This is where a recovered key pays off — issuing application commands the device acts on.", + "note": "Test what the device trusts above the link, the Zigbee Cluster Library (ZCL) commands a Coordinator would send: toggle a relay, unlock a lock, set a thermostat, read attributes. Once you hold the network key you can craft these as encrypted APS frames and inject them, or join a Trust Center / coordinator stack to the network and drive devices legitimately. This is where a recovered key pays off, issuing application commands the device acts on.", "tools": [ - { "tool": "killerbee", "role": "Craft & inject ZCL", "why": "With the network key, use KillerBee's framework (zbscapy / scapy-radio) to build and transmit Zigbee APS/ZCL frames — issue cluster commands (on/off, lock/unlock, level) the target device executes.", "caveat": "Needs the network key (from the Break-crypto step) and a transmit-capable KillerBee radio (ApiMote).", "deps": ["apimote"], "needs": "The network key recovered at the Break-crypto step, plus a transmit-capable KillerBee 802.15.4 radio (ApiMote)." } + { "tool": "killerbee", "role": "Craft & inject ZCL", "why": "With the network key, use KillerBee's framework (zbscapy / scapy-radio) to build and transmit Zigbee APS/ZCL frames, issue cluster commands (on/off, lock/unlock, level) the target device executes.", "caveat": "Needs the network key (from the Break-crypto step) and a transmit-capable KillerBee radio (ApiMote).", "deps": ["apimote"], "needs": "The network key recovered at the Break-crypto step, plus a transmit-capable KillerBee 802.15.4 radio (ApiMote)." } ] } } diff --git a/src/data/toolchains/zwave.js b/src/data/toolchains/zwave.js index 1bd5082..cdac026 100644 --- a/src/data/toolchains/zwave.js +++ b/src/data/toolchains/zwave.js @@ -1,66 +1,66 @@ export default { "status": "complete", "facts": [ - { "k": "Band", "v": "Sub-GHz ISM, region-locked: 908.42 MHz (US) · 868.42 MHz (EU) · plus regional channels (e.g. 921.42 MHz ANZ, 919.82 MHz HK, 922–926 MHz JP). One region per device — pick the right frequency first." }, + { "k": "Band", "v": "Sub-GHz ISM, region-locked: 908.42 MHz (US) · 868.42 MHz (EU) · plus regional channels (e.g. 921.42 MHz ANZ, 919.82 MHz HK, 922 to 926 MHz JP). One region per device, pick the right frequency first." }, { "k": "Modulation / rate", "v": "(G)FSK at three data rates: 9.6 kbps (R1, legacy), 40 kbps (R2) and 100 kbps (R3). Z-Wave Long Range (US 912/920 MHz) adds higher power and star topology." }, - { "k": "PHY / MAC", "v": "ITU-T G.9959 — the open PHY/MAC standard underneath Z-Wave (preamble, frame, CRC, addressing). The proprietary upper stack opened up after Silicon Labs released it (~2016+)." }, - { "k": "Identifiers", "v": "32-bit Home ID (the network, fixed by the primary controller) + 8-bit Node ID (the device, 1–232). Both are visible in the clear in every frame header — the network fingerprint." }, - { "k": "Security", "v": "Legacy S0: AES-128, but during device inclusion the network key is sent encrypted under a FIXED, well-known temporary key (all-zero) — capture the inclusion and you recover the network key. Modern S2 (Gen5/700+): Curve25519 ECDH key exchange at inclusion — the shared secret is never sent, so the S0 capture-the-join break does not apply." }, + { "k": "PHY / MAC", "v": "ITU-T G.9959, the open PHY/MAC standard underneath Z-Wave (preamble, frame, CRC, addressing). The proprietary upper stack opened up after Silicon Labs released it (~2016+)." }, + { "k": "Identifiers", "v": "32-bit Home ID (the network, fixed by the primary controller) + 8-bit Node ID (the device, 1 to 232). Both are visible in the clear in every frame header, the network fingerprint." }, + { "k": "Security", "v": "Legacy S0: AES-128, but during device inclusion the network key is sent encrypted under a FIXED, well-known temporary key (all-zero), capture the inclusion and you recover the network key. Modern S2 (Gen5/700+): Curve25519 ECDH key exchange at inclusion, the shared secret is never sent, so the S0 capture-the-join break does not apply." }, { "k": "Topology / targets", "v": "Source-routed mesh: a primary controller/hub plus routing slaves and end devices. Common targets: door locks, garage/window sensors, thermostats and the controller/hub itself." } ], "reference": null, "layers": { "IG": { - "note": "Work out what the device is before any RF work — no capture yet. Z-Wave's first fork is the region: a US device sits at 908.42 MHz and an EU device at 868.42 MHz (with several other regional channels), and a radio tuned to the wrong one hears nothing — so confirm the frequency before anything else. Then the security generation decides whether the rest of this descent even applies: a legacy S0 device has a known inclusion weakness, while a modern S2 device (Z-Wave Gen5/700 and later) uses Curve25519 ECDH and resists the classic break. The Home ID and Node IDs are sent in the clear in every frame, so once you can hear the network you can fingerprint it.", + "note": "Work out what the device is before any RF work, no capture yet. Z-Wave's first fork is the region: a US device sits at 908.42 MHz and an EU device at 868.42 MHz (with several other regional channels), and a radio tuned to the wrong one hears nothing, so confirm the frequency before anything else. Then the security generation decides whether the rest of this descent even applies: a legacy S0 device has a known inclusion weakness, while a modern S2 device (Z-Wave Gen5/700 and later) uses Curve25519 ECDH and resists the classic break. The Home ID and Node IDs are sent in the clear in every frame, so once you can hear the network you can fingerprint it.", "lookFor": [ - "Region / frequency — US 908.42 MHz vs EU 868.42 MHz vs other regional channels (ANZ 921.42, HK 919.82, JP 922–926…). Read the FCC ID / CE marking on the label; it sets which radio can even tune the device.", - "Chipset / SoC and generation — Sigma Designs ZW0301/ZW0501 (3rd/5th gen, 500-series) vs Silicon Labs 700/800-series (EFR32ZG). FCC ID and teardown; the generation hints at S0-only vs S2 support. Cross-reference Z-Wave advisories (the S0 inclusion key exposure; Z-Shave downgrade).", - "Security class in use — S0 (legacy AES-128, vulnerable inclusion key transport) vs S2 (Curve25519 ECDH, much stronger) vs unencrypted command classes. A controller can also downgrade S2→S0 (Z-Shave) if the device still offers S0.", - "Home ID (32-bit, the network) and Node ID (8-bit, the device) — both sent in the clear in every frame header; the network's fingerprint and your filter once you can hear it.", - "Device type and exposed command classes — door lock, sensor, switch, thermostat, controller/hub — and which command classes it answers (some are sent unencrypted even on a secure network).", - "Data rate it speaks — 9.6 / 40 / 100 kbps (R1/R2/R3), and whether it is classic Z-Wave or Z-Wave Long Range — sets the demodulator parameters at capture." + "Region / frequency, US 908.42 MHz vs EU 868.42 MHz vs other regional channels (ANZ 921.42, HK 919.82, JP 922 to 926…). Read the FCC ID / CE marking on the label; it sets which radio can even tune the device.", + "Chipset / SoC and generation, Sigma Designs ZW0301/ZW0501 (3rd/5th gen, 500-series) vs Silicon Labs 700/800-series (EFR32ZG). FCC ID and teardown; the generation hints at S0-only vs S2 support. Cross-reference Z-Wave advisories (the S0 inclusion key exposure; Z-Shave downgrade).", + "Security class in use, S0 (legacy AES-128, vulnerable inclusion key transport) vs S2 (Curve25519 ECDH, much stronger) vs unencrypted command classes. A controller can also downgrade S2→S0 (Z-Shave) if the device still offers S0.", + "Home ID (32-bit, the network) and Node ID (8-bit, the device), both sent in the clear in every frame header; the network's fingerprint and your filter once you can hear it.", + "Device type and exposed command classes, door lock, sensor, switch, thermostat, controller/hub, and which command classes it answers (some are sent unencrypted even on a secure network).", + "Data rate it speaks, 9.6 / 40 / 100 kbps (R1/R2/R3), and whether it is classic Z-Wave or Z-Wave Long Range, sets the demodulator parameters at capture." ] }, "SP": { - "note": "Confirm the device is transmitting and on which regional channel, before committing a decoder. Z-Wave lives in a narrow sub-GHz ISM slice — one region per device — so 'see it' means tuning a waterfall to the regional centre (908.42 MHz US / 868.42 MHz EU) and watching for the short FSK bursts the device emits when it reports or is polled. A cheap RTL-SDR reaches these sub-GHz bands fine (unlike 2.4 GHz protocols), so this is the one band where the budget dongle is a first-class survey radio; a HackRF gives more bandwidth to watch several channels/rates at once. Z-Wave is bursty and event-driven — trigger the device (open the door, trip the sensor) to make it talk while you watch.", + "note": "Confirm the device is transmitting and on which regional channel, before committing a decoder. Z-Wave lives in a narrow sub-GHz ISM slice, one region per device, so 'see it' means tuning a waterfall to the regional centre (908.42 MHz US / 868.42 MHz EU) and watching for the short FSK bursts the device emits when it reports or is polled. A cheap RTL-SDR reaches these sub-GHz bands fine (unlike 2.4 GHz protocols), so this is the one band where the budget dongle is a first-class survey radio; a HackRF gives more bandwidth to watch several channels/rates at once. Z-Wave is bursty and event-driven, trigger the device (open the door, trip the sensor) to make it talk while you watch.", "tools": [ - { "tool": "gqrx", "role": "Spectrum / waterfall view", "why": "Tune to the regional centre (908.42 MHz US / 868.42 MHz EU) and watch for the short FSK bursts a Z-Wave device emits when it reports or is polled — confirm the device is alive and on the channel you expect before committing a decoder. A cheap RTL-SDR reaches these sub-GHz bands; a HackRF shows more of the band at once.", "deps": ["rtl-sdr-v4", "hackrf-one"] } + { "tool": "gqrx", "role": "Spectrum / waterfall view", "why": "Tune to the regional centre (908.42 MHz US / 868.42 MHz EU) and watch for the short FSK bursts a Z-Wave device emits when it reports or is polled, confirm the device is alive and on the channel you expect before committing a decoder. A cheap RTL-SDR reaches these sub-GHz bands; a HackRF shows more of the band at once.", "deps": ["rtl-sdr-v4", "hackrf-one"] } ] }, "PHY": { - "note": "No standalone Z-Wave demodulator separate from capture in this kit. The G.9959 (G)FSK waveform is demodulated (PHY) and the frame parsed (LL) together inside each capture tool, so PHY and Capture are one step. The job here is to match the demodulator to the device: pick the regional frequency (908.42/868.42 MHz) and the data rate (9.6/40/100 kbps) — Z-Wave's three rates use different deviation/bandwidth, so a decoder set for 100 kbps will miss a 9.6 kbps legacy frame. The SDR path (Waving-Z / rtl-zwave / EZ-Wave) channelises the raw I/Q in software; the vendor Zniffer does demod and framing in the stick's own radio." + "note": "No standalone Z-Wave demodulator separate from capture in this kit. The G.9959 (G)FSK waveform is demodulated (PHY) and the frame parsed (LL) together inside each capture tool, so PHY and Capture are one step. The job here is to match the demodulator to the device: pick the regional frequency (908.42/868.42 MHz) and the data rate (9.6/40/100 kbps), Z-Wave's three rates use different deviation/bandwidth, so a decoder set for 100 kbps will miss a 9.6 kbps legacy frame. The SDR path (Waving-Z / rtl-zwave / EZ-Wave) channelises the raw I/Q in software; the vendor Zniffer does demod and framing in the stick's own radio." }, "LL": { - "note": "Capture and decode Z-Wave frames. Park a radio on the regional channel and pull the frame headers (Home ID, Node ID, frame control, command class) off the air. Two paths: the SDR path demodulates the G.9959 waveform in software — Waving-Z or rtl-zwave on a cheap RTL-SDR for a quick read, or EZ-Wave / Scapy-radio on a HackRF for a scriptable assessment stack — while the vendor path uses Silicon Labs' Zniffer GUI on a UZB stick for a turnkey, fully-dissected capture. CRITICAL for the crypto step: to break an S0 network you must capture a device inclusion (pairing) — power-cycle or re-pair the target while capturing so the inclusion key transport hits the air.", + "note": "Capture and decode Z-Wave frames. Park a radio on the regional channel and pull the frame headers (Home ID, Node ID, frame control, command class) off the air. Two paths: the SDR path demodulates the G.9959 waveform in software, Waving-Z or rtl-zwave on a cheap RTL-SDR for a quick read, or EZ-Wave / Scapy-radio on a HackRF for a scriptable assessment stack, while the vendor path uses Silicon Labs' Zniffer GUI on a UZB stick for a turnkey, fully-dissected capture. CRITICAL for the crypto step: to break an S0 network you must capture a device inclusion (pairing), power-cycle or re-pair the target while capturing so the inclusion key transport hits the air.", "decoder": "wireshark", "tools": [ - { "tool": "waving-z", "role": "Primary SDR decoder", "why": "An ITU-T G.9959 (de)modulator: pipe `rtl_sdr` (or HackRF) I/Q into `wave-in` and it prints decoded Z-Wave frames — the rtl_433-style entry point for getting packets off a ~$30 dongle. Set the regional frequency and data rate to match the device.", "caveat": "Receive-side decoding to stdout; not a full dissector — pair with the Wireshark dissector or EZ-Wave for command-class detail.", "deps": ["rtl-sdr-v4", "hackrf-one"] }, + { "tool": "waving-z", "role": "Primary SDR decoder", "why": "An ITU-T G.9959 (de)modulator: pipe `rtl_sdr` (or HackRF) I/Q into `wave-in` and it prints decoded Z-Wave frames, the rtl_433-style entry point for getting packets off a ~$30 dongle. Set the regional frequency and data rate to match the device.", "caveat": "Receive-side decoding to stdout; not a full dissector, pair with the Wireshark dissector or EZ-Wave for command-class detail.", "deps": ["rtl-sdr-v4", "hackrf-one"] }, { "tool": "rtl-zwave", "role": "Minimal RTL-SDR decoder", "why": "The original G.9959 demodulator Waving-Z grew from: pipe `rtl_sdr` samples in and read decoded frames out. The smallest way to confirm Z-Wave traffic and read Home ID / Node ID headers on a cheap RTL-SDR.", "caveat": "Receive-only, RTL-SDR only; minimal output, older codebase.", "deps": ["rtl-sdr-v4"] }, - { "tool": "ez-wave", "role": "Assessment-suite capture", "why": "ezstumbler does passive discovery and active enumeration over a HackRF (GNU Radio + Scapy-radio), giving a scriptable capture you carry into recon and attack — the canonical Z-Wave assessment toolkit. Default config drives two HackRF One SDRs.", "caveat": "Python 2.7 / GNU Radio 3.7 era; setup is dated and fiddly. The same SDR/Scapy plumbing underlies the attack and app steps.", "deps": ["hackrf-one"] }, + { "tool": "ez-wave", "role": "Assessment-suite capture", "why": "ezstumbler does passive discovery and active enumeration over a HackRF (GNU Radio + Scapy-radio), giving a scriptable capture you carry into recon and attack, the canonical Z-Wave assessment toolkit. Default config drives two HackRF One SDRs.", "caveat": "Python 2.7 / GNU Radio 3.7 era; setup is dated and fiddly. The same SDR/Scapy plumbing underlies the attack and app steps.", "deps": ["hackrf-one"] }, { "tool": "scapy-radio", "role": "Scriptable SDR sniff/craft", "why": "GNU Radio flowgraphs plus a patched Scapy with a Z-Wave layer: sniff, dissect and replay Z-Wave frames straight from a Python session over a HackRF. The radio/Scapy plumbing EZ-Wave builds on, usable standalone to script capture and injection.", "caveat": "Older GNU Radio codebase; the Z-Wave layer is one of several protocols it carries.", "deps": ["hackrf-one"] }, - { "tool": "zwave-zniffer", "role": "Vendor sniffer (turnkey)", "why": "Silicon Labs' official Zniffer GUI (in Simplicity Studio) captures and fully dissects Z-Wave RF — command classes, security handshakes, the inclusion exchange — on a UZB stick flashed with Zniffer firmware. The easiest, most accurate capture when an SDR demod is too fiddly, and the cleanest way to watch an S0 inclusion.", "caveat": "Needs a Silicon Labs UZB stick re-flashed with Zniffer firmware; vendor GUI, not an open-source SDR path.", "deps": ["silabs-uzb7"] } + { "tool": "zwave-zniffer", "role": "Vendor sniffer (turnkey)", "why": "Silicon Labs' official Zniffer GUI (in Simplicity Studio) captures and fully dissects Z-Wave RF, command classes, security handshakes, the inclusion exchange, on a UZB stick flashed with Zniffer firmware. The easiest, most accurate capture when an SDR demod is too fiddly, and the cleanest way to watch an S0 inclusion.", "caveat": "Needs a Silicon Labs UZB stick re-flashed with Zniffer firmware; vendor GUI, not an open-source SDR path.", "deps": ["silabs-uzb7"] } ] }, "CR": { - "note": "Be honest about what is breakable. Z-Wave has two security worlds. LEGACY S0 (AES-128) has a real, well-known weakness: during device inclusion the controller sends the network key encrypted under a FIXED, all-zero temporary key — so anyone who captured that inclusion exchange can decrypt the key transport and recover the network key, then decrypt the rest of the S0 traffic. This is exactly why the Capture step insists on grabbing an inclusion: no inclusion capture, no S0 key. MODERN S2 (Z-Wave Gen5/700+) closes this — inclusion uses a Curve25519 ECDH key exchange, the shared secret is never transmitted, and there is no equivalent capture-the-join shortcut; an S2 recording yields no key offline. (The historical Z-Shave attack instead downgrades an S2-capable device back to S0 during inclusion — a downgrade, not a break of S2's crypto.) So: against S0, capture the inclusion and extract the key; against S2, recognise it and stop.", + "note": "Be honest about what is breakable. Z-Wave has two security worlds. LEGACY S0 (AES-128) has a real, well-known weakness: during device inclusion the controller sends the network key encrypted under a FIXED, all-zero temporary key, so anyone who captured that inclusion exchange can decrypt the key transport and recover the network key, then decrypt the rest of the S0 traffic. This is exactly why the Capture step insists on grabbing an inclusion: no inclusion capture, no S0 key. MODERN S2 (Z-Wave Gen5/700+) closes this, inclusion uses a Curve25519 ECDH key exchange, the shared secret is never transmitted, and there is no equivalent capture-the-join shortcut; an S2 recording yields no key offline. (The historical Z-Shave attack instead downgrades an S2-capable device back to S0 during inclusion, a downgrade, not a break of S2's crypto.) So: against S0, capture the inclusion and extract the key; against S2, recognise it and stop.", "tools": [ - { "tool": "zwave-zniffer", "role": "S0 inclusion capture / key transport", "why": "The cleanest way to capture and read the S0 inclusion exchange — the moment the network key is sent encrypted under the fixed all-zero temporary key. The Zniffer dissects the frames so you can see the key-transport command and, knowing the fixed temporary key, recover the S0 network key; load that key back into the Zniffer (or your decoder) to decrypt the rest of the S0 traffic.", "caveat": "Only the legacy S0 inclusion is exposed this way — S2's ECDH inclusion reveals no key. Needs the UZB stick + Zniffer firmware and a captured (re-)inclusion.", "deps": ["silabs-uzb7"], "needs": "A capture that contains a device INCLUSION on an S0 network — captured at the Capture step (Zniffer, or an SDR decoder watching the join). To force one, exclude and re-include (re-pair) the target while capturing. No inclusion capture means no S0 key." }, - { "tool": "ez-wave", "role": "S0 traffic decryption (with key)", "why": "Once you hold the S0 network key (recovered from the inclusion's fixed-temporary-key transport), EZ-Wave / Scapy-radio can decrypt and dissect the S0 frames it captured over the HackRF — turning ciphertext into readable command classes for recon and attack.", "caveat": "S0 only; against S2 (Curve25519 ECDH) there is no key to recover and nothing to decrypt. Dated Python 2.7 / GNU Radio stack.", "deps": ["hackrf-one"], "needs": "The S0 network key derived from the captured inclusion (the key transport is encrypted under the known fixed all-zero temporary key), plus the S0 capture from the Capture step." } + { "tool": "zwave-zniffer", "role": "S0 inclusion capture / key transport", "why": "The cleanest way to capture and read the S0 inclusion exchange, the moment the network key is sent encrypted under the fixed all-zero temporary key. The Zniffer dissects the frames so you can see the key-transport command and, knowing the fixed temporary key, recover the S0 network key; load that key back into the Zniffer (or your decoder) to decrypt the rest of the S0 traffic.", "caveat": "Only the legacy S0 inclusion is exposed this way, S2's ECDH inclusion reveals no key. Needs the UZB stick + Zniffer firmware and a captured (re-)inclusion.", "deps": ["silabs-uzb7"], "needs": "A capture that contains a device INCLUSION on an S0 network, captured at the Capture step (Zniffer, or an SDR decoder watching the join). To force one, exclude and re-include (re-pair) the target while capturing. No inclusion capture means no S0 key." }, + { "tool": "ez-wave", "role": "S0 traffic decryption (with key)", "why": "Once you hold the S0 network key (recovered from the inclusion's fixed-temporary-key transport), EZ-Wave / Scapy-radio can decrypt and dissect the S0 frames it captured over the HackRF, turning ciphertext into readable command classes for recon and attack.", "caveat": "S0 only; against S2 (Curve25519 ECDH) there is no key to recover and nothing to decrypt. Dated Python 2.7 / GNU Radio stack.", "deps": ["hackrf-one"], "needs": "The S0 network key derived from the captured inclusion (the key transport is encrypted under the known fixed all-zero temporary key), plus the S0 capture from the Capture step." } ] }, "AT": { - "note": "Going active means transmitting in licensed-exempt sub-GHz ISM and injecting into someone's home-automation network — authorised testing only, on devices you own or have permission to assess. What is possible depends entirely on the crypto from the previous step. On a legacy S0 network where you recovered the key (or against UNENCRYPTED command classes, which exist even on secure networks), you can forge and inject command-class frames — replay a captured command, or craft a new one (e.g. a lock/unlock, switch on/off) and transmit it. The TX path is the SDR side of the same tools: EZ-Wave / Scapy-radio over a HackRF, or gr-zwave_poore as a GNU Radio TX block on a USRP B210. Against a properly-configured S2 network you cannot forge valid encrypted frames without the key, and S2 adds nonce-based anti-replay — so injection there is limited to whatever the device still exposes unencrypted.", + "note": "Going active means transmitting in licensed-exempt sub-GHz ISM and injecting into someone's home-automation network, authorised testing only, on devices you own or have permission to assess. What is possible depends entirely on the crypto from the previous step. On a legacy S0 network where you recovered the key (or against UNENCRYPTED command classes, which exist even on secure networks), you can forge and inject command-class frames, replay a captured command, or craft a new one (e.g. a lock/unlock, switch on/off) and transmit it. The TX path is the SDR side of the same tools: EZ-Wave / Scapy-radio over a HackRF, or gr-zwave_poore as a GNU Radio TX block on a USRP B210. Against a properly-configured S2 network you cannot forge valid encrypted frames without the key, and S2 adds nonce-based anti-replay, so injection there is limited to whatever the device still exposes unencrypted.", "tools": [ - { "tool": "ez-wave", "role": "Inject / forge command classes", "why": "With the S0 key (or against unencrypted command classes), EZ-Wave's Scapy-radio stack crafts and transmits Z-Wave command-class frames over a HackRF — replay a captured command or forge a new one (switch, lock, sensor report) into the target network.", "caveat": "Effective against S0 (with the key) and unencrypted classes; S2's ECDH + anti-replay nonces block forged/replayed encrypted frames. Authorised testing only.", "deps": ["hackrf-one"], "needs": "For encrypted S0 targets, the network key from the Break-crypto step; for unencrypted command classes, just a capture to model the frame. Plus a TX-capable HackRF on the device's regional frequency." }, - { "tool": "scapy-radio", "role": "Scriptable replay / injection", "why": "Build and transmit arbitrary Z-Wave frames from a Scapy session over a HackRF — the flexible path to replay a captured frame wholesale or fuzz/forge command classes when you want full control of the bytes.", "caveat": "Same S0-vs-S2 limits as above; older GNU Radio codebase. Authorised testing only.", "deps": ["hackrf-one"], "needs": "A captured frame to replay, or the S0 key to forge valid encrypted frames, plus a TX-capable HackRF on the regional frequency." }, - { "tool": "gr-zwave_poore", "role": "GNU Radio Z-Wave TX block", "why": "A maintained GNU Radio out-of-tree module that transmits Z-Wave signals (tested on a USRP B210, branches for GNU Radio 3.7/3.8/3.10, integrated into FISSURE) — the flowgraph path to generate/replay Z-Wave frames when you prefer a GNU Radio block to the Scapy-radio stack.", "caveat": "Primarily a transmitter; pair with an SDR decoder for RX. Authorised testing only.", "deps": ["usrp-b210"], "needs": "The frame/payload to transmit (a captured command, or a forged one using the S0 key from the Break-crypto step) and a TX-capable USRP B210 on the regional frequency." } + { "tool": "ez-wave", "role": "Inject / forge command classes", "why": "With the S0 key (or against unencrypted command classes), EZ-Wave's Scapy-radio stack crafts and transmits Z-Wave command-class frames over a HackRF, replay a captured command or forge a new one (switch, lock, sensor report) into the target network.", "caveat": "Effective against S0 (with the key) and unencrypted classes; S2's ECDH + anti-replay nonces block forged/replayed encrypted frames. Authorised testing only.", "deps": ["hackrf-one"], "needs": "For encrypted S0 targets, the network key from the Break-crypto step; for unencrypted command classes, just a capture to model the frame. Plus a TX-capable HackRF on the device's regional frequency." }, + { "tool": "scapy-radio", "role": "Scriptable replay / injection", "why": "Build and transmit arbitrary Z-Wave frames from a Scapy session over a HackRF, the flexible path to replay a captured frame wholesale or fuzz/forge command classes when you want full control of the bytes.", "caveat": "Same S0-vs-S2 limits as above; older GNU Radio codebase. Authorised testing only.", "deps": ["hackrf-one"], "needs": "A captured frame to replay, or the S0 key to forge valid encrypted frames, plus a TX-capable HackRF on the regional frequency." }, + { "tool": "gr-zwave_poore", "role": "GNU Radio Z-Wave TX block", "why": "A maintained GNU Radio out-of-tree module that transmits Z-Wave signals (tested on a USRP B210, branches for GNU Radio 3.7/3.8/3.10, integrated into FISSURE), the flowgraph path to generate/replay Z-Wave frames when you prefer a GNU Radio block to the Scapy-radio stack.", "caveat": "Primarily a transmitter; pair with an SDR decoder for RX. Authorised testing only.", "deps": ["usrp-b210"], "needs": "The frame/payload to transmit (a captured command, or a forged one using the S0 key from the Break-crypto step) and a TX-capable USRP B210 on the regional frequency." } ] }, "AP": { - "note": "Above the link sits the application — the Z-Wave command classes the device exposes: lock/unlock (Door Lock CC), on/off (Binary Switch CC), thermostat setpoints, sensor reports, configuration parameters, and the Version/Manufacturer-Specific classes that fingerprint it. Two ways to drive them. Read them out of capture: EZ-Wave's ezrecon interrogates a device for its manufacturer/model, firmware version, supported command classes and configuration (and ezfingerprint identifies the module generation). Or drive them legitimately from a controller: Silicon Labs' Z-Wave PC Controller, over a UZB stick, includes/excludes nodes and sends command-class messages to the device — the supported, vendor way to enumerate and exercise what the device trusts above the link (and to set up controlled S0/S2 inclusions to study at the lower steps).", + "note": "Above the link sits the application, the Z-Wave command classes the device exposes: lock/unlock (Door Lock CC), on/off (Binary Switch CC), thermostat setpoints, sensor reports, configuration parameters, and the Version/Manufacturer-Specific classes that fingerprint it. Two ways to drive them. Read them out of capture: EZ-Wave's ezrecon interrogates a device for its manufacturer/model, firmware version, supported command classes and configuration (and ezfingerprint identifies the module generation). Or drive them legitimately from a controller: Silicon Labs' Z-Wave PC Controller, over a UZB stick, includes/excludes nodes and sends command-class messages to the device, the supported, vendor way to enumerate and exercise what the device trusts above the link (and to set up controlled S0/S2 inclusions to study at the lower steps).", "tools": [ - { "tool": "ez-wave", "role": "Device recon / command-class enumeration", "why": "ezrecon interrogates a Z-Wave device — manufacturer and model, software/firmware versions, supported command classes and configuration settings — and ezfingerprint identifies the module generation via a PHY preamble-length trick. The fastest read of what application surface the device exposes, over a HackRF.", "caveat": "Active interrogation transmits to the device; dated Python 2.7 / GNU Radio stack. Authorised testing only.", "deps": ["hackrf-one"] }, - { "tool": "zwave-pc-controller", "role": "Controller / command-class driver", "why": "Silicon Labs' official PC Controller drives a real Z-Wave controller node over a UZB stick's Serial API: include/exclude nodes, browse the device's supported command classes and send them — the supported way to enumerate and exercise the application layer, and to stage controlled S0/S2 inclusions you then study at the capture/crypto steps.", "caveat": "Vendor GUI; needs a Silicon Labs UZB stick. Operates as a legitimate controller rather than a covert injector.", "deps": ["silabs-uzb7"], "needs": "A Silicon Labs UZB stick running the Serial API (controller firmware). To exercise a target you must be able to include it into your test network (or already be its controller)." } + { "tool": "ez-wave", "role": "Device recon / command-class enumeration", "why": "ezrecon interrogates a Z-Wave device, manufacturer and model, software/firmware versions, supported command classes and configuration settings, and ezfingerprint identifies the module generation via a PHY preamble-length trick. The fastest read of what application surface the device exposes, over a HackRF.", "caveat": "Active interrogation transmits to the device; dated Python 2.7 / GNU Radio stack. Authorised testing only.", "deps": ["hackrf-one"] }, + { "tool": "zwave-pc-controller", "role": "Controller / command-class driver", "why": "Silicon Labs' official PC Controller drives a real Z-Wave controller node over a UZB stick's Serial API: include/exclude nodes, browse the device's supported command classes and send them, the supported way to enumerate and exercise the application layer, and to stage controlled S0/S2 inclusions you then study at the capture/crypto steps.", "caveat": "Vendor GUI; needs a Silicon Labs UZB stick. Operates as a legitimate controller rather than a covert injector.", "deps": ["silabs-uzb7"], "needs": "A Silicon Labs UZB stick running the Serial API (controller firmware). To exercise a target you must be able to include it into your test network (or already be its controller)." } ] } } diff --git a/src/lib/taxonomy.js b/src/lib/taxonomy.js index a78babc..1bf282b 100644 --- a/src/lib/taxonomy.js +++ b/src/lib/taxonomy.js @@ -1,5 +1,5 @@ export const LAYER_IDS = ['IG', 'SP', 'PHY', 'LL', 'CR', 'AT', 'AP']; -// Rank a layer by its position in the descent (IG=0 … AP=6) — for ordering controls +// Rank a layer by its position in the descent (IG=0 … AP=6), for ordering controls // the way the methodology teaches them, rather than alphabetically by id. export const layerRank = (id) => LAYER_IDS.indexOf(id);