ICEBERG Labs

Como hicimos ingenieria inversa a un sistema de pulseras LED chinas para crear nuestro propio software de programacion.

Reverse Engineering USB HID UART Sniffing Python ESP32 Hardware Hacking

La Aventura Completa

Pista Falsa

Fase 1: Capturamos el trafico USB equivocado

Empezamos con Wireshark capturando TODO el trafico USB mientras programabamos pulseras con 10, 60 y 180 minutos. Analizamos 40KB de datos hexadecimales con un script Python que comparaba byte por byte.

Encontramos 591 diferencias... pero ninguna escalaba con el tiempo. Despues de renderizar los datos como imagen, descubrimos que eran tickets de la impresora 3nStar, no del programador.

$ python analizar_pulseras.py
Diferencias encontradas: 591 bytes
Bytes que escalan con tiempo: 0
Conclusion: El tiempo NO esta en los datos USB...
(porque estabamos viendo la impresora de recibos)
Dispositivo encontrado

Fase 2: Descubrimos que es un HID, no una impresora

Investigando en el Administrador de Dispositivos encontramos el programador real: un dispositivo HID con VID=0x1A86, PID=0xE010. El fabricante: WCH.CN, producto: "HID To Serial".

Escribimos un lector HID en Python y capturamos los primeros mensajes del dispositivo:

[IN] 06 05 46 41 49 4C 21 = "FAIL!" (sin pulsera)
[IN] 04 05 4F 4B 9F = "OK" (pulsera detectada)

Pero cuando intentamos ENVIAR comandos... el dispositivo los ignoraba todos. Probamos cientos de formatos: ACK, NAK, STX/ETX, ASCII, binario, checksums. Nada funcionaba.

Caos controlado

Fase 3: Enviamos basura y el dispositivo reacciono

En un test de diagnostico, enviamos bytes 0xAA repetidos para probar tamanios de reporte. De repente: el dispositivo sono, los LEDs cambiaron de color y el IR empezo a parpadear.

Pero los resultados eran completamente inconsistentes. El mismo comando a veces hacia algo, a veces no. Probamos el header AA 55, y parecia un protocolo real, pero los resultados seguian siendo erraticos.

AA 55 01 = verde (a veces)
AA 55 04 = azul (a veces)
AA 55 06 = ciclo colores (a veces)
AA 55 05 = ciclo completo (a veces nada)
Consistencia: ~30% ... inaceptable
Punto de inflexion

Fase 4: Abrimos el programador con destornillador

Decidimos ir al hardware. Con un destornillador abrimos el programador y encontramos dos chips principales:

Chip 1: CH9326 (WCH) - Puente USB HID a UART
Chip 2: STC 8C2K32S2 - Microcontrolador 8051
Chip 3: UL26 - Regulador de voltaje
Chip 4: SS14 - Diodo Schottky

Esto lo cambio todo. Ahora sabiamos que el CH9326 es un puente transparente USB-UART. Los datos que enviamos por HID se convierten a serial y llegan al STC. Solo necesitabamos espiar esa comunicacion serial.

Hardware hacking

Fase 5: Soldamos cables al UART interno con un ESP32

Conectamos un ESP32 directamente a las lineas UART entre el CH9326 y el STC. Literalmente espiando la conversacion entre los dos chips dentro del programador.

Hubo un momento de panico: al conectar el cable al pin TXD, el IR dejo de funcionar. Solucion: usar una resistencia de 10K para no cargar la linea.

ESP32 GPIO16 --[10K]-- CH9326 TXD (PC->MCU)
ESP32 GPIO17 --------- STC TX (MCU->PC)
ESP32 GND ------------ GND programador

IMPORTANTE: NO usar los pines TX/RX del ESP32
(esos son para Serial Monitor, GPIO 1 y 3)
Protocolo descifrado

Fase 6: Capturamos el protocolo real por primera vez

Con el sniffer activo y el software original corriendo, vimos por primera vez los bytes REALES del protocolo:

[MCU->PC] 05 46 41 49 4C 21 | .FAIL! (6 bytes)
[PC->MCU] 05 52 00 3C 47 00 0A 42 00 1E 44 (11 bytes)
R 60m G 10m B 30m checksum

El protocolo era HERMOSO en su simplicidad:
[header] [R] [tiempo] [G] [tiempo] [B] [tiempo] [checksum]

Tambien descubrimos POR QUE los comandos anteriores eran inconsistentes: el CH9326 usa el primer byte como longitud. Nuestro header 0x05 se interpretaba como "envia 5 bytes" en vez de ser parte del protocolo. Faltaba anteponer 0x0B (11 bytes).

Objetivo completado

Fase 7: Primera pulsera programada con nuestro codigo

Con el protocolo decodificado, creamos programar_pulsera.py. Un ultimo obstaculo: la pulsera no encendia porque el software original de Kpoplight seguia corriendo en segundo plano, sobreescribiendo nuestros tiempos con ceros.

Al cerrar el software del fabricante y ejecutar solo el nuestro:

$ python programar_pulsera.py

PROGRAMADOR DE PULSERAS LED
Kpoplight Magnetic Locker Band

[OK] Programador conectado

Rojo=1min Verde=1min Azul=1min
Esperando pulsera... (programadas: 0)

>>> PULSERA #1 PROGRAMADA! <<<

El Protocolo Descifrado

11 bytes que controlan todo el sistema

Formato del paquete

ByteHexASCIIFuncion
0 05 ENQ Header fijo
1 52 'R' Marcador Rojo
2-3 00 3C Tiempo Rojo: 60 minutos
4 47 'G' Marcador Verde
5-6 00 0A Tiempo Verde: 10 minutos
7 42 'B' Marcador Azul
8-9 00 1E Tiempo Azul: 30 minutos
10 44 Checksum (suma & 0xFF)
17+
Scripts de prueba creados
256
Comandos probados por fuerza bruta
2
Chips identificados en el PCB
11
Bytes del protocolo final
9600
Baud rate del UART interno
1
Dia para descifrarlo todo

Proxima Fase

Sistema propio de gestion para ICEBERG

En desarrollo

Interfaz web para programar pulseras desde cualquier dispositivo
Integracion con sistema de venta y cobro
Panel de administracion con reportes y estadisticas
Historial de pulseras programadas
Configuracion de paquetes y precios por color/tiempo
100% independiente del software chino