Documentation
¶
Overview ¶
Package applecontinuity decodes Apple Continuity BLE advertisement payloads — the Manufacturer-Specific-Data blob Apple devices broadcast for Handoff, AirDrop, Nearby Info / Action, AirPods proximity pairing, iBeacon, Hey Siri, and the other ad-hoc connectivity primitives that make the Apple ecosystem feel "magical" on a sniffer.
Wrap-vs-native judgement
Native. The Continuity protocol is undocumented by Apple but has been extensively reverse-engineered: Mertens et al. (furiousMAC, 2019), Stute et al. (TU Darmstadt 2019- 2024), AppleJuice, hexway/apple_bleee, and the Wireshark dissectors all converge on the same TLV structure and the same per-type field semantics. The wire format is a tight Type/Length/Value walker — no crypto, no variable-length integers, no compression at this layer. Operators paste the Manufacturer Specific Data bytes (post-Apple-Company-ID 0x004C) from a Wireshark BLE capture, a Sniffle/CatSniffer dump, an hcidump trace, or any BLE scanner and inspect every documented field.
What this package covers
Outer envelope tolerance: the input may be the raw TLV stream (e.g. "1005...10 05..."), the post-CompanyID manufacturer data ("4C00 10 05..."), or the full advertising-data record ("0BFF4C00 10 05..."). The walker auto-detects each form and strips down to the TLV bytes.
TLV walking: each message inside the stream is (Type[1] + Length[1] + Value[Length]). Multiple messages per advertisement are common (e.g. Nearby Info + Handoff frequently appear together).
Type table (per furiousMAC + AppleJuice + Wireshark): 0x02 iBeacon (RFC-equivalent: Apple's own spec, publicly documented as the iBeacon protocol) 0x03 AirPrint 0x04 AirDrop 0x05 HomeKit 0x06 Proximity Pairing (AirPods / Beats / etc.) 0x07 Hey Siri 0x08 AirPlay Source 0x09 AirPlay Target 0x0A Magic Switch (Apple Pencil) 0x0B Watch Connection 0x0C Handoff 0x0D WiFi Settings Target 0x0E Tethering Target (Instant Hotspot) 0x0F Nearby Action 0x10 Nearby Info
Per-type body decoding (best-effort, headline fields):
iBeacon (0x02, length 21): UUID (16 bytes hex) + Major (uint16 BE) + Minor (uint16 BE) + TX Power (int8 dBm). The canonical Apple-issued spec.
Handoff (0x0C, variable): Clipboard-state byte + IV (2 bytes) + AuthTag (1 byte) + Encrypted Payload.
Nearby Info (0x10, variable): high nibble of byte 0 = StatusFlags, low nibble = ActionCode (15-entry name table); byte 1 = DataFlags; remaining bytes = AuthTag.
Nearby Action (0x0F, variable): ActionFlags byte
ActionType byte (15-entry name table for setup flows: Wi-Fi join, AirPods setup, HomePod auto-setup, Apple TV setup, etc.) + AuthTag + optional ActionParameters.
AirDrop (0x04, length 18): Status byte + 8 bytes of Apple ID / phone / email hash material.
Proximity Pairing (0x06, variable): Device model byte
status flags + battery levels (Left + Right + Case for AirPods) + UTP (Unknown Transport Pairing) + Lid state.
Hey Siri (0x07, length 5): Hash bytes used to wake Siri across devices.
Other types: surfaced with Type + TypeName + Length
raw hex body. Operators who need full dissection of AirPlay, HomeKit, or Watch frames can read the bytes.
Multi-TLV summary: a per-advertisement summary string (e.g. "Nearby Info + Handoff") for triage.
What this package does NOT cover (deliberately out of scope)
The BLE Link-Layer / Advertising PDU framing — that's `ble_classify` / `ble_findmy_*`.
The AppleID / phone / email / OfflineFinding key reversal — encrypted material is surfaced as hex; the decryption side belongs in a separate Spec.
Handoff payload decryption — IV + AuthTag are surfaced but the cipher-text is opaque without the pairing key.
The Bluetooth Low Energy GAP / GATT layer beyond the advertising data record.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type AirDrop ¶
type AirDrop struct {
StatusHex string `json:"status_hex"`
IdentifierHex string `json:"identifier_hex"`
}
AirDrop is the body of message type 0x04.
type Handoff ¶
type Handoff struct {
ClipboardStatus string `json:"clipboard_status"`
IVHex string `json:"iv_hex"`
AuthTagHex string `json:"auth_tag_hex"`
PayloadHex string `json:"encrypted_payload_hex"`
}
Handoff is the body of message type 0x0C.
type HeySiri ¶
type HeySiri struct {
HashHex string `json:"hash_hex"`
}
HeySiri is the body of message type 0x07.
type IBeacon ¶
type IBeacon struct {
UUID string `json:"uuid"`
Major uint16 `json:"major"`
Minor uint16 `json:"minor"`
TXPower int8 `json:"tx_power_dbm"`
}
IBeacon is the body of message type 0x02.
type Message ¶
type Message struct {
Type int `json:"type"`
TypeHex string `json:"type_hex"`
TypeName string `json:"type_name"`
Length int `json:"length"`
BodyHex string `json:"body_hex,omitempty"`
IBeacon *IBeacon `json:"ibeacon,omitempty"`
Handoff *Handoff `json:"handoff,omitempty"`
NearbyInfo *NearbyInfo `json:"nearby_info,omitempty"`
NearbyAction *NearbyAction `json:"nearby_action,omitempty"`
AirDrop *AirDrop `json:"airdrop,omitempty"`
HeySiri *HeySiri `json:"hey_siri,omitempty"`
ProxPairing *ProxPairing `json:"proximity_pairing,omitempty"`
}
Message is one decoded Continuity TLV entry.
type NearbyAction ¶
type NearbyAction struct {
ActionFlags int `json:"action_flags"`
ActionType int `json:"action_type"`
ActionTypeName string `json:"action_type_name"`
AuthTagHex string `json:"auth_tag_hex,omitempty"`
ParametersHex string `json:"parameters_hex,omitempty"`
}
NearbyAction is the body of message type 0x0F.
type NearbyInfo ¶
type NearbyInfo struct {
StatusFlags int `json:"status_flags"`
StatusBits string `json:"status_bits_decoded"`
ActionCode int `json:"action_code"`
ActionName string `json:"action_name"`
DataFlags int `json:"data_flags,omitempty"`
AuthTagHex string `json:"auth_tag_hex,omitempty"`
}
NearbyInfo is the body of message type 0x10.
type ProxPairing ¶
type ProxPairing struct {
DeviceModel int `json:"device_model"`
DeviceModelHex string `json:"device_model_hex"`
StatusFlags int `json:"status_flags"`
BatteryLeft int `json:"battery_left_pct,omitempty"`
BatteryRight int `json:"battery_right_pct,omitempty"`
BatteryCase int `json:"battery_case_pct,omitempty"`
LidState int `json:"lid_state,omitempty"`
RawHex string `json:"raw_hex,omitempty"`
}
ProxPairing is the body of message type 0x06 (AirPods / Beats).