Skip to content
KitploitKITPLOIT
FerramentasBlog
Log in
Enviar
FerramentasBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

FeedsContatoPrivacidade© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
CMF-Watch-Pro-2-BLE-Protocol — Protocolo BLE com engenharia reversa para o CMF Watch Pro 2, documentando layout GATT, quadros de comando criptografados AES-128-CBC, handshake de autenticação e sincronização de dados de saúde para desenvolvimento de aplicativo companheiro alternativo. | Kitploit
Ferramentas/GitHubGitHub/joshuapassos/cmf-watch-pro-2-ble-protocol
Segurança de Sistemas EmbarcadosSegurança BluetoothSegurança IoTEngenharia ReversaSegurança Sem FioCriptografiaSegurança MóvelSegurança de Hardware e IoTAnálise de Firmware

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar
GitHubjoshuapassos/cmf-watch-pro-2-ble-protocol

CMF-Watch-Pro-2-BLE-Protocol

Protocolo BLE com engenharia reversa para o CMF Watch Pro 2, documentando layout GATT, quadros de comando criptografados AES-128-CBC, handshake de autenticação e sincronização de dados de saúde para desenvolvimento de aplicativo companheiro alternativo.

Ver RepositórioSite
343há 2 mesesAinda não revisado

CMF Watch Pro 2 — Protocolo BLE (engenharia reversa)

Não oficial. Este documento descreve o protocolo Bluetooth Low Energy (BLE) do CMF Watch Pro 2 (CMF by Nothing), reconstruído por engenharia reversa para um aplicativo complementar alternativo. Não é afiliado nem endossado pela Nothing/CMF. Use por sua conta e risco.

Todos os inteiros multibyte no cabeçalho do quadro e opcodes são big-endian. Inteiros dentro de payloads de comando são little-endian, salvo indicação em contrário (isso reflete o firmware do dispositivo) — cuidado com as exceções (GOALS_SET, GPS_PUSH, offset/comprimento de transferência em massa são big-endian).

Marcadores de confiança

Cada afirmação não óbvia abaixo é marcada com a forma como foi estabelecida:

  • ✅ validado no dispositivo — observado em uma captura ao vivo descriptografada ou testado contra um relógio real.
  • 🔎 de firmware / RE do APK — extraído por descompilação do firmware (1.0.0.73) ou do APK oficial (3.5.7); consistente com o código, mas não testado em tempo de execução.
  • 🟡 parcialmente comprovado — estabelecido estruturalmente (offline, em todo o corpus ou por RE), mas a etapa restante precisa do relógio e ainda não foi executada.
  • ⚠️ [incerto] — inferido, não confirmado; pode estar errado.

Quando uma seção posterior corrige uma anterior, o texto anterior é mantido com um ponteiro em vez de ser excluído — saber quais leituras foram tentadas e refutadas poupa à próxima pessoa o mesmo desvio.

Dispositivo de teste para todas as capturas: CMF Watch Pro 2-5485, fw 1.0.0.73, serial CI04102520008192, MCU Actions ATS3089C (Cortex-M4), tela 466×360.


1. Layout GATT

O telefone é o cliente GATT; o relógio é o periférico, anunciando-se como CMF Watch Pro 2-XXXX (4 caracteres hexadecimais).

FinalidadeServiçoCaracterísticaPropriedades
Escrita de comando0000fff0-0000-1000-8000-00805f9b34fb0000fff2-…Write
Notificação de comando0000fff0-…0000fff1-…Notify
Escrita de shell (AT)—77d4ff01-2fe2-2334-0d35-9ccd078f529cWrite
Notificação de shell (AT)—77d4ff02-…Notify
Escrita de dados em massa—02f00000-0000-0000-0000-00000000ffe1Write
Notificação de dados em massa—02f00000-…ffe2Notify

Ative as notificações escrevendo 01 00 em cada CCCD (00002902-…). O canal de comando (fff1/fff2) transporta o protocolo enquadrado abaixo. O canal de shell (77d4…) transporta texto simples no estilo AT (ex.: AT GETSECRET; ver §14). O canal de dados (02f0…) transporta grandes blobs binários (mostrador, firmware, AGPS), coordenados por opcodes de controle no canal de comando.

UUIDs de serviço — o relógio anuncia ~10 serviços primários. Enumerados em uma unidade real: 0xfff0 (comando), 0x180f (bateria), 0x180a (informações do dispositivo), 0xefe7, 0xffd0, 02f00000-…ffe0 e 02f00000-…fe00 (dados), 77d4e67c-2fe2-2334-0d35-9ccd078f529c (shell / pareamento), e49a3001-f69a-11e8-8eb2-f2801f1b9fd1, f48a23c0-f69a-11e8-8eb2-f2801f1b9fd1.

⚠️ O serviço de shell tem UUID 77d4e67c-…, não 77d4ff00-…. Revisões anteriores deste documento presumiam que o serviço compartilhava o prefixo ff00 de suas características (77d4ff01/77d4ff02, §14) — não compartilha, pelo menos na unidade em que isso foi verificado (descoberta de freethinkel/fmc, ver §Fontes). Os UUIDs das características são inalterados. Não verificado se 77d4e67c é estável entre unidades — enumere em vez de codificar.

🌐 Observação sobre Web Bluetooth. O Chromium apenas descobre serviços que a página listou em optionalServices, mesmo para uma chamada getPrimaryServices() sem filtro — uma página que lista 3 serviços vê 3, enquanto chrome://bluetooth-internals (a própria camada C++ do Chrome, sem escopo) mostra todos os 10. Se você escrever um cliente de navegador, liste todos os UUIDs acima antecipadamente ou o pareamento falhará com serviços que claramente existem. Sem Web Bluetooth no Firefox/Safari; requer um gesto do usuário + HTTPS/localhost.

✅ Uma sessão real inteira rodou no único canal de comando — durante uma captura de 160 s de uso intenso, não houve tráfego nos canais de dados/firmware ou shell, exceto durante uma transferência explícita de OTA/mostrador.


2. Formato de quadro (0xF5)

Toda mensagem do canal de comando é encapsulada em um ou mais quadros com cabeçalho de 11 bytes:``` +------+-----------+--------+-------------+-------------+--------+-------------------+ | 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` juntos formam o **opcode** (ver §6). 🔎 confirmado no construtor de frames do app oficial (`C6117b.m30831g`).
- `chunkCount` = total de chunks para este comando; `chunkIndex` é **baseado em 1**.
- `chunkLen` = número de bytes de `chunk` neste frame.
- Uma única escrita BLE pode ser fragmentada pelo MTU do link; o receptor armazena os bytes brutos e re-extrai frames completos. Payloads grandes são divididos em múltiplos chunks (mesmo `cmd1/cmd2`, com `chunkIndex` crescente) e remontados em ordem.

### Convenção de opcode (✅ confirmado no wire)

- `cmd1 = 0xFFFF`: `cmd2` em `0x80xx`/`0x90xx` = telefone→relógio (requisição/definição); `0x00xx`/`0xa0xx` = relógio→telefone (resposta). Os pares correspondem pelo byte baixo (`0x9055`↔`0xa055`, `0x8051`↔`0x0051`).
- `cmd1` específico de funcionalidade: sufixo de `cmd2` = `0x0001` **SET**, `0x0002` **GET**, `0x0003` **ACK**.

### Corpo do chunk

Para cada chunk, o corpo é `payloadPiece ‖ CRC32_LE(payloadPiece)` (CRC de 4 bytes, little-endian, zlib/IEEE). Se o comando for **criptografado** (ver §3), todo o `payloadPiece ‖ CRC` é então criptografado com AES-128-CBC/PKCS7 e esse ciphertext torna-se o `chunk` do frame.

**Peculiaridade do plaintext:** para opcodes em plaintext, o relógio *conta* o CRC de 4 bytes em `chunkLen`, mas **não** o transmite. Portanto, ao decodificar um frame em plaintext, o comprimento real dos dados é `chunkLen − 4`. (Frames criptografados carregam o CRC dentro do ciphertext, como de costume.)

Dimensionamento do chunk (para que chunks criptografados caiam em limites de bloco AES), com `maxWrite = mtu − 3`:
- criptografado: `floor((maxWrite − 11) / 16) * 16 − 4 − 1`
- plaintext: `maxWrite − 11 − 4 − 1`

✅ Todos os valores de `chunkLen` observados em frames criptografados eram múltiplos de 16 (o alinhamento de bloco é mantido).

---

## 3. Primitivas criptográficas

- **AES-128-CBC** com preenchimento **PKCS7** e um **IV fixo** (do firmware `CmfCharacteristic.AES_IV`):
  `50 51 52 53 54 55 56 57 60 61 62 63 64 65 66 5A`.
- **CRC32** (zlib/IEEE), emitido como 4 bytes little-endian.
- **SHA-256** sobre a concatenação das partes.

Derivação de chave:```
authkey      = SHA256( rnd1 ‖ rnd2 ‖ secret )[0..16]      // persisted across sessions
sessionKey   = SHA256( nonce ‖ authkey )[0..16]           // per connection
  • secret = segredo do dispositivo de 16 bytes (obtido do relógio via comando de shell AT GETSECRET → GETSECRET:<32-hex>,OK).
  • rnd1 = 16 bytes aleatórios escolhidos pelo telefone; rnd2 = 16 bytes aleatórios do relógio.
  • nonce = bytes da resposta de nonce do relógio.

Após a chave ser definida, todos os quadros do canal de comandos são criptografados com AES, exceto os opcodes de texto simples listados na §5.

Baixar ferramenta