Skip to content
KitploitKITPLOIT
StrumentiExploitsBlog
Log in
Invia
StrumentiExploitsBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

FeedContattoPrivacy© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
CMF-Watch-Pro-2-BLE-Protocol — Protocollo BLE reverse-engineered per il CMF Watch Pro 2, con documentazione del layout GATT, frame di comando crittografati AES-128-CBC, handshake di autenticazione e sincronizzazione dei dati sulla salute per lo sviluppo di app companion alternative. | Kitploit
Strumenti/GitHubGitHub/joshuapassos/cmf-watch-pro-2-ble-protocol
Sicurezza Sistemi EmbeddedSicurezza BluetoothSicurezza IoTReverse EngineeringSicurezza WirelessCrittografiaSicurezza MobileSicurezza Hardware e IoTAnalisi del Firmware

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi
GitHubjoshuapassos/cmf-watch-pro-2-ble-protocol

CMF-Watch-Pro-2-BLE-Protocol

Protocollo BLE reverse-engineered per il CMF Watch Pro 2, con documentazione del layout GATT, frame di comando crittografati AES-128-CBC, handshake di autenticazione e sincronizzazione dei dati sulla salute per lo sviluppo di app companion alternative.

Vedi RepositorySito web
3492 mesi faNon ancora revisionato

CMF Watch Pro 2 — Protocollo BLE (reverse-engineered)

Non ufficiale. Questo documento descrive il protocollo Bluetooth Low Energy (BLE) del CMF Watch Pro 2 (CMF by Nothing), ricostruito tramite reverse engineering per un'app companion alternativa. Non è affiliato né approvato da Nothing/CMF. Utilizzo a proprio rischio.

Tutti gli interi multi-byte nell'header del frame e negli opcode sono big-endian. Gli interi all'interno dei payload dei comandi sono little-endian salvo diversa indicazione (questo rispecchia il firmware del dispositivo) — attenzione alle eccezioni (GOALS_SET, GPS_PUSH, offset/lunghezza del trasferimento bulk sono big-endian).

Indicatori di affidabilità

Ogni affermazione non ovvia di seguito è etichettata con il metodo con cui è stata stabilita:

  • ✅ validato sul dispositivo — osservato in una cattura live decifrata o testato su un orologio reale.
  • 🔎 da firmware / RE dell'APK — estratto decompilando il firmware (1.0.0.73) o l'APK ufficiale (3.5.7); coerente con il codice ma non testato a runtime.
  • 🟡 parzialmente provato — stabilito strutturalmente (offline, su tutto il corpus, o tramite RE) ma il passaggio rimanente richiede l'orologio e non è stato eseguito.
  • ⚠️ [incerto] — dedotto, non confermato; potrebbe essere errato.

Dove una sezione successiva corregge una precedente, il testo precedente viene mantenuto con un riferimento piuttosto che eliminato — sapere quali letture sono state provate e confutate evita alla persona successiva lo stesso giro.

Dispositivo di test per tutte le catture: CMF Watch Pro 2-5485, fw 1.0.0.73, seriale CI04102520008192, MCU Actions ATS3089C (Cortex-M4), schermo 466×360.


1. Layout GATT

Il telefono è il client GATT; l'orologio è il periferico, che si pubblicizza come CMF Watch Pro 2-XXXX (4 caratteri esadecimali).

ScopoServizioCaratteristicaProprietà
Scrittura comandi0000fff0-0000-1000-8000-00805f9b34fb0000fff2-…Write
Notifica comandi0000fff0-…0000fff1-…Notify
Scrittura shell (AT)—77d4ff01-2fe2-2334-0d35-9ccd078f529cWrite
Notifica shell (AT)—77d4ff02-…Notify
Scrittura dati bulk—02f00000-0000-0000-0000-00000000ffe1Write
Notifica dati bulk—02f00000-…ffe2Notify

Abilita le notifiche scrivendo 01 00 su ogni CCCD (00002902-…). Il canale comandi (fff1/fff2) trasporta il protocollo incapsulato descritto di seguito. Il canale shell (77d4…) trasporta testo in stile AT semplice (es. AT GETSECRET; vedi §14). Il canale dati (02f0…) trasporta grandi blob binari (watchface, firmware, AGPS), coordinati da opcode di controllo sul canale comandi.

UUID dei servizi — l'orologio pubblicizza ~10 servizi primari. Enumerati su un'unità reale: 0xfff0 (comandi), 0x180f (batteria), 0x180a (info dispositivo), 0xefe7, 0xffd0, 02f00000-…ffe0 e 02f00000-…fe00 (dati), 77d4e67c-2fe2-2334-0d35-9ccd078f529c (shell / accoppiamento), e49a3001-f69a-11e8-8eb2-f2801f1b9fd1, f48a23c0-f69a-11e8-8eb2-f2801f1b9fd1.

⚠️ L'UUID del servizio shell è 77d4e67c-…, non 77d4ff00-…. Revisioni precedenti di questo documento assumevano che il servizio condividesse il prefisso ff00 delle sue caratteristiche (77d4ff01/77d4ff02, §14) — non è così, almeno sull'unità su cui è stato verificato (risultato da freethinkel/fmc, vedi §Fonti). Gli UUID delle caratteristiche sono invariati. Non verificato se 77d4e67c sia stabile tra le unità — enumerare piuttosto che hardcodare.

🌐 Nota su Web Bluetooth. Chromium scopre solo i servizi che la pagina ha elencato in optionalServices, anche per una chiamata getPrimaryServices() non filtrata — una pagina che elenca 3 servizi ne vede 3, mentre chrome://bluetooth-internals (il livello C++ di Chrome, non limitato) mostra tutti e 10. Se scrivi un client browser, elenca tutti gli UUID sopra in anticipo o l'accoppiamento fallirà con servizi che esistono chiaramente. Nessun Web Bluetooth in Firefox/Safari; richiede un gesto dell'utente + HTTPS/localhost.

✅ Un'intera sessione reale è stata eseguita sul solo canale comandi — durante una cattura di 160 s di uso intensivo non c'è stato traffico sui canali dati/firmware o shell tranne durante un trasferimento esplicito OTA/watchface.


2. Formato frame (0xF5)

Ogni messaggio sul canale comandi è incapsulato in uno o più frame con header di 11 byte:``` +------+-----------+--------+-------------+-------------+--------+-------------------+ | 0xF5 | chunkLen | cmd1 | chunkCount | chunkIndex | cmd2 | chunk bytes … | | 1 B | 2 B (BE) | 2 B BE | 2 B BE | 2 B BE | 2 B BE | chunkLen bytes | +------+-----------+--------+-------------+-------------+--------+-------------------+ __________________________ 11-byte header ____________________________/

- `cmd1`/`cmd2` insieme formano l'**opcode** (vedi §6). 🔎 confermato rispetto al frame builder
  dell'app ufficiale (`C6117b.m30831g`).
- `chunkCount` = numero totale di chunk per questo comando; `chunkIndex` è **1-based**.
- `chunkLen` = numero di byte di `chunk` in questo frame.
- Una singola scrittura BLE può essere frammentata dall'MTU del link; il ricevitore bufferizza i byte
  grezzi e ri-estrae i frame completi. I payload di grandi dimensioni vengono suddivisi in più chunk
  (stesso `cmd1/cmd2`, `chunkIndex` crescente) e riassemblati in ordine.

### Convenzione opcode (✅ confermata sul wire)

- `cmd1 = 0xFFFF`: `cmd2` in `0x80xx`/`0x90xx` = telefono→orologio (richiesta/impostazione); `0x00xx`/`0xa0xx` =
  orologio→telefono (risposta). Le coppie corrispondono tramite il byte basso (`0x9055`↔`0xa055`, `0x8051`↔`0x0051`).
- `cmd1` specifico della funzionalità: suffisso `cmd2` = `0x0001` **SET**, `0x0002` **GET**, `0x0003` **ACK**.

### Corpo del chunk

Per ogni chunk, il corpo è `payloadPiece ‖ CRC32_LE(payloadPiece)` (CRC a 4 byte, little-endian,
zlib/IEEE). Se il comando è **cifrato** (vedi §3), l'intero `payloadPiece ‖ CRC` viene poi
cifrato con AES-128-CBC/PKCS7 e quel ciphertext diventa il `chunk` del frame.

**Stranezza del plaintext:** per gli opcode in chiaro l'orologio *conta* il CRC a 4 byte in `chunkLen` ma
**non** lo trasmette. Quindi, decodificando un frame in chiaro, la lunghezza effettiva dei dati è `chunkLen − 4`.
(I frame cifrati trasportano il CRC all'interno del ciphertext come di consueto.)

Dimensionamento dei chunk (così i chunk cifrati cadono sui confini dei blocchi AES), con `maxWrite = mtu − 3`:
- cifrato: `floor((maxWrite − 11) / 16) * 16 − 4 − 1`
- in chiaro: `maxWrite − 11 − 4 − 1`

✅ Tutti i valori `chunkLen` dei frame cifrati osservati erano multipli di 16 (l'allineamento dei blocchi è rispettato).

---

## 3. Primitive crittografiche

- **AES-128-CBC** con padding **PKCS7** e un **IV fisso** (dal firmware
  `CmfCharacteristic.AES_IV`):
  `50 51 52 53 54 55 56 57 60 61 62 63 64 65 66 5A`.
- **CRC32** (zlib/IEEE), emesso come 4 byte little-endian.
- **SHA-256** sulla concatenazione delle parti.

Derivazione della chiave:```
authkey      = SHA256( rnd1 ‖ rnd2 ‖ secret )[0..16]      // persisted across sessions
sessionKey   = SHA256( nonce ‖ authkey )[0..16]           // per connection
  • secret = segreto del dispositivo a 16 byte (ottenibile dall'orologio tramite il comando shell AT GETSECRET → GETSECRET:<32-hex>,OK).
  • rnd1 = 16 byte casuali scelti dal telefono; rnd2 = 16 byte casuali dall'orologio.
  • nonce = byte dalla risposta nonce dell'orologio.

Dopo che la chiave è impostata, tutti i frame del canale di comando sono crittografati AES tranne gli opcode in chiaro elencati in §5.

Scarica lo strumento