core-jmp core-jmpdeath of core jump

Caeruleus: BLE Security Testing Without the Scavenger Hunt

Praetorian's Caeruleus is one Go binary on Linux/BlueZ that replaces hcitool, gatttool, bettercap BLE, and throwaway Bleak scripts: scan, enumerate, assess unpaired reads, DFU doors, and fuzz writable GATT characteristics with JSON for humans and agents.

oxfemale September 11, 2026 19 min read 84 reads
Export PDF
Caeruleus: BLE Security Testing Without the Scavenger Hunt
Original text: "Bluetooth Low Energy Security Testing, Consolidated: Introducing Caeruleus"Aaron Wasserman, Hunter Ver Helst, Siddhant Kalgutkar, and Will McCardell, Praetorian (10 July 2026); Praetorian 5th Legion. Tool: github.com/praetorian-inc/caeruleus (Apache-2.0). Code, tables and figures below are reproduced verbatim with attribution captions.
Smartwatch, lock, earbuds and tracker under a blue radio glow
BLE is a short-range notebook of named drawers. Caeruleus is one binary that opens them, audits them, and fuzzes the ones that write.
Isometric BLE devices: a smartwatch, smart lock, earbuds and tracker emitting Bluetooth signals under a red attack glow
Original hero. Source: original article.
Caeruleus GitHub banner: BLE security testing consolidated into one Go binary
Repository banner from the Apache-2.0 project. Source: github.com/praetorian-inc/caeruleus.

Executive Summary

Bluetooth Low Energy is how a phone talks to a lock, a watch, a glucose sensor, a tractor ECU, a conference badge. The radio is cheap and the firmware is often older than the intern who last touched it. The testing stack is worse: deprecated hcitool, a full-fat bettercap install just to print a GATT tree, gatttool tutorials from 2016, and a Bleak script you swear you will tidy up next quarter. Praetorian’s IoT engineers got tired of being the glue. On 10 July 2026 they released Caeruleus — Latin for the deep blue in Bluetooth — one Go binary on Linux/BlueZ that scans, enumerates, reads, writes, listens, fuzzes, and runs structured assess workflows with JSON an agent can eat.

This draft keeps every command, table, and walkthrough from the Praetorian post, then adds the kitchen picture of GATT as a shared notebook, a stack diagram, the GitHub command map (including assess pairing the blog barely names), and a defender checklist for unpaired reads, DFU doors, and write-without-response smash. Schema.org on the original page lists 2,167 words. This one is longer on purpose. It will not sniff, MITM, or clone a peripheral: Caeruleus cannot, and we will not pretend it can.

Caeruleus — Latin, deep blue

Praetorian, 10 July 2026

BLE for People Who Do Not Own a Sniffer

Two people whispering across a table with a shared notebook
GATT is a notebook of named slots. If a slot says anyone may read, anyone nearby with a laptop can.
Central versus peripheral and three example GATT characteristics
Caeruleus is always the central. The lock is the peripheral. Encryption is a padlock firmware often forgets to close.

Classic Bluetooth is a cable replacement. BLE is a noticeboard. A peripheral advertises “I am a heart-rate strap.” A central connects and sees a tree of services and characteristics. Each characteristic has a handle (a small integer like 0x0015), a UUID (standard 0x2A37 or a vendor 128-bit), and properties: Read, Write, Write-without-response, Notify, Indicate. Pairing and encryption are optional. Many medical and industrial gadgets ship with every interesting drawer marked world-readable. That is not a crypto break. That is a missing checkbox in the GATT database.

Kitchen table: Imagine a hotel key rack in the lobby. Some hooks have a sign “staff only” that nobody enforces. Caeruleus is a visitor who reads the signs, copies what is not locked, and then shakes the unlocked drawers to see if the rack falls over. It does not hide in the bushes with a radio telescope (sniffing) and it does not glue a fake rack next to the real one (cloning / AITM).
For operators: ATT&CK does not have a neat T-code for “unauthenticated GATT read.” Closest enterprise cousins: T1040 (sniffing — out of scope here), T1557 (MITM — also out of scope), T1200 hardware additions if you bring a dongle. ICS: T0860 Wireless Compromise. The findings that matter on an engagement are still CWE-306 (missing authentication), CWE-319 (cleartext sensitive data), CWE-120 (WWR overflow), and unauthenticated DFU (supply-chain of one device).

The BLE Testing Tax

Six old BLE tools collapsing into one caeruleus binary
You used to be the integration layer, copying MAC addresses between terminals. That is the tax.

Pick a random BLE guide. You will be told to use hcitool lescan (deprecated, gone from many distros), bettercap ble.recon (a network-attack framework with libpcap/libusb/Ruby-era baggage, just to browse GATT), gatttool (deprecated for years, still in every tutorial), and a custom Bleak or pygatt script for anything real. BlueZ’s supported frontends are bluetoothctl and btmgmt: they manage the adapter and pair a headset. They are the wrong abstraction for an assessment. None of them emit JSON the next step can parse. You become the bus.

Caeruleus keeps abstractions at the level a human or an agent actually works: scan, enumerate, read, write, listen, assess, fuzz. Secrets in characteristic values are run through Praetorian’s open-source Titus rule set. Results can be JSON for scripts.

Use casePrevious methodUsing Caeruleus
Discovering nearby deviceshcitool lescan / bettercap ble.recon / bluetoothctl scan oncaeruleus scan
Listing (and reading) services/characteristicsbettercap ble.enumcaeruleus enumerate -b <mac> --values
An interactive sessiongatttool -I / bluetoothctl menu gattcaeruleus shell -b <mac>
Reading a handlegatttool --char-read-hnd 0x0013caeruleus read -b <mac> -a 0x0013
Writing to a handlegatttool -b de:ad:be:ef:be:f1 --char-write-req -a 0x002c -n $(echo -n "some value"|xxd -ps)caeruleus write -b de:ad:be:ef:be:f1 -a 0x002c --req -s "some value"
Capturing notificationscustom Bleak notification loggercaeruleus listen -b <mac> -a <handle>
Checking unauth data exposurecustom Bleak audit scriptscaeruleus recon / caeruleus assess ...
Fuzzing a characteristiccustom write fuzzers / boofuzzcaeruleus fuzz write -b <mac> -a <handle>
Connection params, MTUhcitool con / btmgmt con-infocaeruleus conn-params -b <mac>
Adapter power and recoverybtmgmt power / hciconfig reset / rfkillcaeruleus doctor / caeruleus adapter power cycle
The scavenger hunt versus one binary. Source: original article.

Agents Welcome Here

-o json and -o jsonl are marked authoritative, not a CSV afterthought. The repo ships an agentskills.io Skill at skills/caeruleus/SKILL.md that teaches any compatible assistant the command surface and a recommended methodology. Praetorian’s benchmark: Opus 4.8 xHigh with Caeruleus and the skill used 62% of the time and 70% of the tokens versus the same model with free tool choice (it picked hcitool and Bleak).

Kitchen table: You can tell a junior “run nmap.” You could not tell an intern “run BLE testing” without a scavenger hunt. A skill file plus JSON is how you tell a model the same sentence and get a findings array instead of a screenshot of bluetoothctl.

Ergonomics That Sound Small Until You Live in a Faraday Closet

BLE health

caeruleus doctor walks BlueZ and kernel state: bluetoothd running, adapter powered, no leaked discovery session, BlueZ-cached address matches MGMT chip-live address, a 2-second LE scan probe, ExchangeMTU in a safe band. Failures come with a fix command, e.g. caeruleus adapter power cycle. Exit 0 = all-clear, 2 = a check failed (grep/diff convention).

Clean teardown: SIGTERM/SIGHUP run the disconnect path and poll until Connected=false hits BlueZ, so the peripheral re-advertises instead of sitting in a 10–30 second ghost connection after gatttool dies. Anyone who has fuzzed a lock and then waited for the supervision timeout knows this tax.

Output formats

  • text — borderless tables so MACs and UUIDs are double-click selectable.
  • json — indented, canonical.
  • jsonl — one object per event for listen and scan --live.
  • enumerate --compact — one key=value line per characteristic for grep or a tight LLM window.

Scripting

  • Daemon: caeruleus serve holds one GATT connection on a Unix socket. caeruleus send "read 0x0029" avoids the ~1.5 s reconnect per CLI spawn.
  • Batch: caeruleus batch -b $ADDR reads commands from stdin, ignores blanks and # comments, no readline, no async pump. -b connects up front.
  • Atomic trigger-then-capture: listen --trigger-handle / --trigger-value set up notifications, write, capture. Separate commands miss the notify.

Convenience

  • Device type from GAP Appearance + advertised UUIDs (0x00C2 + Heart Rate Service → “Smartwatch”).
  • Handles: 0x002a, 0X2A, or 42. Hex: deadbeef, de:ad:be:ef, de ad be ef, 0xdeadbeef.
  • caeruleus recipes — 16 workflows in the blog, 19 in the current README; caeruleus recipes trigger searches by keyword.
  • conn-params — interval, peripheral latency, supervision timeout, whether the peripheral renegotiated. gatttool and bettercap do not show this.

Opinionated: What It Will Not Do

Central only, never peripheral. No sniffing, no active AITM/MITM, no cloning. If you need Ubertooth/nRF sniffer, a GATTacker-style clone, or a pairing-mode downgrade over the air, bring another tool. Caeruleus is the GATT clerk, not the radio tap.

For operators: Linux only. README is explicit: no macOS, no Windows. Raw-socket commands need root: conn-params, monitor, fuzz write --raw, cccd --raw, raw-write, mtu --set, bdaddr --set. Older BlueZ (e.g. 5.55) hides remote GAP/GATT from D-Bus; enumerate --raw (root) walks ATT directly for true handles.

A Quick Walkthrough

Sanity-check the adapter, then see what is yelling in the 2.4 GHz ISM band:

$ caeruleus doctor
adapter: hci0
  [  OK] bluetoothd            active
  [  OK] Powered               true
  [  OK] Discovering           false
  [  OK] Address agreement     00:1A:7D:DA:71:13
  [  OK] LE scan healthy       saw advertisements
  [  OK] ExchangeMTU           247
$ caeruleus scan
ADDRESS            TYPE    RSSI  DEVICE  NAME
------------------------------------------------------------
9C:9C:1F:F2:88:86  public  -32           BLECTF_JohnsonSpace
C9:F0:81:C6:3B:52  random  -50           Govee_H61B5_3B52
C4:C0:B0:3B:5B:EF  random  -59           Aranet4 06D4B
DC:FD:B4:CA:B4:E9  random  -62           JBL Boombox 2

Browse the GATT tree and read every characteristic in one shot:

$ caeruleus enumerate -b 9C:9C:1F:F2:88:86 --values
SVC HND  CHR HND  CHR UUID  PROPS        HEX                ASCII
0x0014   0x0015   0x2A00    R            424c457b46344c...  BLE{F4K3_1D3NT1TY}
0x0028   0x002b   0xFF02    R,W          577269746520...    Write Flags Here
0x0028   0x002d   0xFF03    R            424c457b503447...  BLE{T0K3N_S4V3R}
0x0028   0x002f   0xFF05    R,W          577269746520...    Write anything here
0x0028   0x004f   0xFF16    B,R,W,N,ext  536f206d616e79...  So many properties!

Poke individual handles. The write-then-read on 0x002f is the CTF-shaped demo from the post:

$ caeruleus read -b 9C:9C:1F:F2:88:86 -a 0x002d
0x002d hex=424c457b503447335f5455524e5e33527d ascii="BLE{T0K3N_S4V3R}"

$ caeruleus write -b 9C:9C:1F:F2:88:86 -a 0x002f -s "praetorian"
0x002f written=10 type=request

$ caeruleus read -b 9C:9C:1F:F2:88:86 -a 0x002f
0x002f hex=424c457b43304c30535333554d7d ascii="BLE{C0L0SS3UM}"

Interactive shell (gatttool-style verbs), stdin batch, and serve/send hold one connection across many operations. BLECTF_JohnsonSpace is a lab/CTF target in the screenshot, not a production lock. Do not fuzz a stranger’s insulin pump on the train.

Repeatable Assessment Workflows

Handle I/O is the easy part. recon fingerprints and audits the tree. Each assess probes one weakness class. The blog lists four; the GitHub README adds pairing:

  • assess check-auth — what an unpaired attacker can read (or write with --probe-write in the README).
  • assess encryption — whether pairing/encryption requirements are actually enforced.
  • assess pairing — SMP feature exchange and downgrade resistance (README; not in the original comparison table).
  • assess dfu — exposed, unauthenticated firmware-update entry points.
  • assess wwr — write-without-response overflow and rapid-fire resilience.

Every assessment emits {address, test, summary, findings[]} with per-finding severity, handle, uuid, evidence. Titus escalates a hardcoded key on an unpaired link to high:

$ caeruleus assess check-auth -b CC:B6:0E:3C:97:0B -o json | jq '.findings[] | select(.severity=="high")'
{
  "title": "Secret readable without authentication",
  "severity": "high",
  "handle": 19,
  "uuid": "00ca0001-bede-ad43-4145-52554c455500",
  "evidence": "6177735f...774a61 (\"aws_access_key_id=AKIADEADBEEFDEADBEEF aws_secret_access_key=wJa\") +37 bytes",
  "detail": "Titus matched rule \"AWS API Credentials\"; value read over an unpaired, unencrypted link."
}
Kitchen table: That finding is the hotel key rack with an AWS access key hanging on a public hook. No pairing. No encryption. The tester did not “hack Bluetooth.” They asked the rack politely.

Writable characteristic, throwaway Bleak fuzzer replaced:

$ sudo caeruleus fuzz write -b CC:B6:0E:3C:97:0B -a 0x0015 --raw --max-iter 20 --max-time 15s
[+] opening session to CC:B6:0E:3C:97:0B
[+] target=0x0002 liveness=0x0002 seeds=13 out=fuzz-out-20260701T144803Z
[+] done iter=2 states=2 queue=2 crashes=1 hangs=0 elapsed=1m2s
[+] results in fuzz-out-20260701T144803Z

$ jq '{mut, op, resp_op, crash}' fuzz-out-20260701T144803Z/crashes/*.json
{
  "mut": "swap",
  "op": "write_req",
  "resp_op": "disconnect",
  "crash": true
}

fuzz replay reproduces a crash. Corpus on disk, crash/hang triage built in. Root is required for --raw.

Command Map from the Repo (Apache-2.0)

The blog is the story. The README is the map. Global flags on every command: -b/--bdaddr, -i/--adapter (default hci0), -t/--timeout, -o/--format, -q/--quiet, -v/--verbose.

GroupCommands
Discoveryscan, enumerate, primary, characteristics
GATT operationsread, write, raw-write, listen, cccd, mtu
Connection managementpair/unpair, conn-params, disconnect, forget
Scriptingshell, batch, serve/send
Security assessmentrecon, assess check-auth, encryption, pairing, wwr, dfu
Fuzzingfuzz write (incl. --raw), fuzz replay
Adapter and diagnosticsdoctor, adapter, bdaddr, monitor
Command reference from the GitHub README. Source: praetorian-inc/caeruleus (Apache-2.0).

Extensible by design

Each assess is one Go file plus one line in assess.go. Shared primitives: session management, findings schema, Titus, structured output. Repeat a manual check twice, upstream it, everyone gets JSON and agent-drivability in the next build.

Part of the Praetorian Toolkit

Same philosophy as Nerva (service fingerprinting), Vespasian (API discovery), Hadrian (API authorization), Brutus (credential testing): one binary, structured output, no dependency hell, now at the RF layer. Titus is the shared secrets engine. Caeruleus is not a full-device assessment. A connected product is also the mobile app, the cloud API, the DFU pipeline, and identity. Praetorian’s close is a sales paragraph; the engineering claim still stands without it.

Getting Started

go install github.com/praetorian-inc/caeruleus/cmd/caeruleus@latest

Or a prebuilt x86_64/arm64 archive from Releases. From source:

git clone https://github.com/praetorian-inc/caeruleus
cd caeruleus
make build        # -> ./caeruleus
make test         # unit tests + shell tests

Needs Linux, BlueZ (bluetoothd), a standard BLE adapter. Run doctor first, then scan. Issues and new assess workflows welcome. License: Apache-2.0.

A Methodology You Can Run on a Lab Peripheral

  1. caeruleus doctor until exit 0. If LE scan fails, power-cycle the adapter before blaming the lock.
  2. caeruleus scan -o jsonl and pick by RSSI and name. Random addresses rotate; do not key your notes on the MAC alone if it is RPA.
  3. enumerate -b $ADDR --values -o json unpaired. That is the check-auth baseline.
  4. assess check-auth, encryption, pairing, dfu, wwr. Keep the JSON. Titus hits on AWS/GitHub/private keys are report-ready.
  5. For each writable handle you care about, fuzz write with a short --max-time first. Replay crashes. Do not fuzz a device you cannot reflash.
  6. If you need sniffing or a fake peripheral, stop. That is nRF Sniffer / GATTacker territory, not this binary.
For operators: Legal: BLE assessments on devices you do not own, in public, can be a wiretap or computer-misuse problem depending on jurisdiction. Lab, written RoE, spare hardware. The BLECTF flags in the walkthrough are a CTF. Production medical devices are not.

Defender View: What a Vendor Should Fear from This Tool

  • Characteristics with Read and no encryption/authentication that hold tokens, Wi-Fi PSKs, serials, session keys.
  • DFU characteristics writable without pairing. That is firmware replace from the parking lot.
  • Write-without-response with no length check. Disconnect-on-swap in the fuzz JSON is a crash, sometimes a useful one.
  • Encryption flags in the GATT database that SMP does not actually enforce (assess encryption).
  • Just-works pairing with no MITM protection if you later add a sniffer (out of Caeruleus, still in the threat model).

Mitigations are boring and sufficient for most gadgets: require bonding before sensitive characteristics, LE Secure Connections, reject WWR on bounded fields, DFU behind a signed bootloader and a physical confirm, no AWS keys in firmware. Caeruleus will still enumerate. It should fail check-auth on anything that matters.

FAQ from the Original Page

What is Caeruleus?

A free, open-source BLE security testing tool from Praetorian: one Go binary on BlueZ covering scan, enumerate, read/write/notify, fuzz, and structured assessment.

How is it different from bettercap, gatttool, and hcitool?

Those tools were never designed to work together and do not emit machine-readable output. Caeruleus is one command surface, JSON/JSONL, no dependency hell.

Can AI agents use it?

Yes: -o json/jsonl plus an Agent Skill. Benchmark: 62% time, 70% tokens versus free tool choice.

Limitations?

Central only. No sniff, no AITM, no clone. Linux/BlueZ only.

Install?

go install github.com/praetorian-inc/caeruleus/cmd/caeruleus@latest or a GitHub release binary. doctor then scan.

What Pairing, DFU and WWR Actually Mean on a Bench

Pairing is a handshake, not a vault

BLE pairing (SMP) negotiates whether the link will be encrypted and whether a human has to confirm a passkey. Just Works is the default on gadgets without a display: both sides agree on a key with no MITM protection. Legacy pairing is still in the wild and is breakable with a sniffer. assess pairing in Caeruleus looks at the feature exchange and whether a downgrade is accepted. That is not the same as assess encryption, which asks: the characteristic said it needed encryption, did the stack actually refuse the unpaired read? Firmware authors set the GATT flag and forget the stack config. Testers have been filing that bug since 2015. The tool just makes the file JSON.

DFU is the firmware front door

Nordic, Dialog, TI, and a dozen module vendors ship a Device Firmware Update service. In development it is wide open so the intern can flash from nRF Connect. In production it is supposed to demand a signed image and often a button. assess dfu looks for the development posture still enabled: an unauthenticated write that takes you to bootloader. If that finding is real, the rest of the product security is a suggestion. An attacker in radio range replaces the firmware. Caeruleus will not write a malicious image for you. It will tell you the door is unlocked. Do not walk through it on a customer device without RoE that explicitly allows bricking.

Write-without-response is a firehose

A Write Request waits for an ATT acknowledgement. Write Command (WWR) does not. Stacks that copy WWR payloads into a fixed buffer without a length check are a gift. assess wwr and fuzz write --raw are how you find the disconnect-on-swap crash in the blog’s JSON. A disconnect is not always a security bug. A watchdog reset that leaves DFU open is. Triage the crash, do not file “fuzz made it drop” as Critical.

Kitchen table: Pairing is asking the lock to put on a padlock. DFU is asking it to accept a new brain. WWR is shouting numbers through the mail slot as fast as you can. Caeruleus checks whether the padlock clicks, whether the brain-slot is open to strangers, and whether shouting knocks the lock off the door.

BlueZ, D-Bus, and Why gatttool Will Not Come Back

Linux BLE is BlueZ. Userland talks to bluetoothd over D-Bus. The kernel speaks HCI to the dongle. Old tutorials call hcitool and gatttool, which spoke HCI/ATT more directly and bit-rotted when BlueZ moved the brain into bluetoothd. Caeruleus uses D-Bus for the polite path and raw L2CAP/HCI when you pass --raw or when D-Bus lies (old BlueZ hiding GAP/GATT). That is why some commands need root and why doctor checks that the address BlueZ cached matches the chip. A mismatch is how you scan on hci0 while the packets leave hci1.

Ghost connections: when a central dies without a proper terminate, the peripheral keeps the link until supervision timeout (often 10–30 s) and will not advertise. Fuzzers that SIGKILL themselves poison the next run. Caeruleus intercepts SIGTERM/SIGHUP and waits for Connected=false. That single behavior is worth the binary if you have ever sat in a closet waiting for a lock to remember it is a lock.

# typical first five minutes on a lab dongle
sudo systemctl status bluetooth
caeruleus doctor || caeruleus adapter power cycle
caeruleus scan --live -o jsonl | tee /tmp/ble-scan.jsonl
ADDR=9C:9C:1F:F2:88:86
caeruleus enumerate -b "$ADDR" --values -o json > /tmp/gatt.json
caeruleus assess check-auth -b "$ADDR" -o json > /tmp/check-auth.json

How This Fits a Full IoT Engagement

Praetorian’s close is correct even if you never hire them. BLE is one face. Also test: the companion app (hardcoded keys, backup BLE commands), the cloud API (device identity, BOLA on serial numbers), the update server, UART/JTAG if the case opens. Caeruleus replaces the BLE scavenger hunt, not the rest of the week. Pipe JSON into the same report factory you use for Burp. A high from Titus on handle 19 is the same shape as a TruffleHog hit in an APK.

  • If check-auth is clean but the app pairs Just Works and then reads secrets, the bug is in the app’s trust of the link, not in GATT flags. Still a finding. Caeruleus pairing/encryption assess is the evidence.
  • If DFU is closed over BLE but open over USB-CDC, say so. Radio tools will not see the USB door.
  • If the device uses a random address, log the IRK only if you have it from a paired dump; otherwise identify by advertised name + manufacturer data + RSSI room.

Authors and Housekeeping

Aaron Wasserman (lead OSE, IoT/hardware, medical and semiconductor, Georgia Tech M.S., OSCP, ACIP, DEF CON / CypherCon / HackSpaceCon). Hunter Ver Helst (OSE, web/mobile/code review, UF CS, BSCP). Siddhant Kalgutkar (application and hardware, CTFs). Will McCardell (listed; bio on the original page is a stub). Built with Praetorian’s 5th Legion. Published 10 July 2026 under IoT Security, Labs, Offensive Security, Open Source Tools. Word count on the page schema: 2,167. This draft is the longer cut.

Key Takeaways

  • BLE testing was a scavenger hunt across deprecated binaries. Caeruleus is one Go binary that speaks BlueZ and JSON.
  • GATT is a notebook of slots. Unpaired readable slots with secrets are high findings without any crypto break.
  • doctor tells you if the adapter is the problem. Ghost-connection teardown saves the 30-second sulk after a crash.
  • assess turns “I poked a few handles” into {findings[]} with Titus on the values.
  • Fuzz write + replay replaces the Bleak fuzzer you were ashamed of. Root for –raw.
  • It will not sniff or MITM. Do not file a finding that required a sniffer and cite this tool.
  • Apache-2.0. Linux only. Write a new assess as one Go file when you repeat a check.

Defensive Recommendations

  1. On every BLE product: require LE Secure Connections + bonding before any characteristic that holds secrets or DFU.
  2. Mark unused write/WWR properties off. Fuzzers love leftover vendor characteristics from the SDK sample.
  3. Never store cloud credentials in GATT. Titus will find them in one unpaired enumerate.
  4. DFU must demand a signed image and a local confirm. assess dfu is looking for the opposite.
  5. Test with Caeruleus (or equivalent) in CI against a lab unit: check-auth JSON should be empty of highs.
  6. If you need sniffing coverage, add a sniffer to the lab; do not pretend the clerk tool is a tap.
  7. Document GAP Appearance and advertised UUIDs. Device-type inference is how an agent decides “this is a lock” in 200 ms.

Conclusion

Wasserman, McCardell, Kalgutkar, Ver Helst and Praetorian’s 5th Legion did not invent BLE security. They stopped paying the tax of five terminals and a deprecated man page. Caeruleus is the clerk who lists the drawers, reads the unlocked ones, shakes the writable ones, and files JSON. The radio is still 2.4 GHz and the firmware is still late. The difference is you can now tell a human or a model: run doctor, scan, enumerate –values, assess check-auth, and do not copy a MAC by hand again.

Original text: “Bluetooth Low Energy Security Testing, Consolidated: Introducing Caeruleus” by Aaron Wasserman, Hunter Ver Helst, Siddhant Kalgutkar, and Will McCardell at Praetorian. Tool: https://github.com/praetorian-inc/caeruleus (Apache-2.0).

oxfemale Vulnerability research, reverse engineering, and exploit development.
// Discussion