<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Proyecto ICEBERG - Ingenieria Inversa Pulseras LED</title>
    <style>
        * { margin: 0; padding: 0; box-sizing: border-box; }
        body {
            font-family: 'Segoe UI', system-ui, sans-serif;
            background: #0a0a0f;
            color: #e0e0e0;
            line-height: 1.7;
        }

        .hero {
            min-height: 100vh;
            display: flex;
            align-items: center;
            justify-content: center;
            text-align: center;
            background: linear-gradient(135deg, #0a0a2e 0%, #1a0a2e 50%, #0a1a2e 100%);
            position: relative;
            overflow: hidden;
        }
        .hero::before {
            content: '';
            position: absolute;
            width: 600px; height: 600px;
            background: radial-gradient(circle, rgba(0,150,255,0.15) 0%, transparent 70%);
            top: -100px; right: -100px;
            animation: pulse 4s ease-in-out infinite;
        }
        .hero::after {
            content: '';
            position: absolute;
            width: 400px; height: 400px;
            background: radial-gradient(circle, rgba(255,0,100,0.1) 0%, transparent 70%);
            bottom: -50px; left: -50px;
            animation: pulse 5s ease-in-out infinite reverse;
        }
        @keyframes pulse {
            0%, 100% { transform: scale(1); opacity: 0.5; }
            50% { transform: scale(1.2); opacity: 1; }
        }
        .hero-content { position: relative; z-index: 1; padding: 2rem; }
        .hero h1 {
            font-size: 3.5rem;
            font-weight: 800;
            background: linear-gradient(90deg, #00d4ff, #7b2fff, #ff0080);
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
            margin-bottom: 1rem;
        }
        .hero .subtitle {
            font-size: 1.3rem;
            color: #8888aa;
            max-width: 600px;
            margin: 0 auto 2rem;
        }
        .hero .tag {
            display: inline-block;
            background: rgba(255,255,255,0.08);
            border: 1px solid rgba(255,255,255,0.15);
            padding: 0.4rem 1rem;
            border-radius: 50px;
            font-size: 0.85rem;
            color: #aaa;
            margin: 0.2rem;
        }

        .timeline {
            max-width: 900px;
            margin: 0 auto;
            padding: 4rem 2rem;
        }
        .timeline h2 {
            text-align: center;
            font-size: 2rem;
            margin-bottom: 3rem;
            color: #fff;
        }

        .phase {
            position: relative;
            padding-left: 60px;
            margin-bottom: 3rem;
        }
        .phase::before {
            content: '';
            position: absolute;
            left: 20px; top: 0; bottom: -3rem;
            width: 2px;
            background: linear-gradient(to bottom, rgba(100,100,255,0.4), rgba(100,100,255,0.1));
        }
        .phase:last-child::before { display: none; }

        .phase-dot {
            position: absolute;
            left: 11px; top: 5px;
            width: 20px; height: 20px;
            border-radius: 50%;
            border: 3px solid;
        }
        .phase-dot.red { border-color: #ff4444; background: rgba(255,68,68,0.2); }
        .phase-dot.yellow { border-color: #ffaa00; background: rgba(255,170,0,0.2); }
        .phase-dot.green { border-color: #00ff88; background: rgba(0,255,136,0.2); }
        .phase-dot.blue { border-color: #4488ff; background: rgba(68,136,255,0.2); }

        .phase-card {
            background: rgba(255,255,255,0.04);
            border: 1px solid rgba(255,255,255,0.08);
            border-radius: 16px;
            padding: 1.8rem;
            transition: all 0.3s;
        }
        .phase-card:hover {
            background: rgba(255,255,255,0.07);
            border-color: rgba(255,255,255,0.15);
            transform: translateX(5px);
        }
        .phase-card h3 {
            font-size: 1.3rem;
            margin-bottom: 0.5rem;
        }
        .phase-card .status {
            display: inline-block;
            padding: 0.2rem 0.7rem;
            border-radius: 50px;
            font-size: 0.75rem;
            font-weight: 600;
            text-transform: uppercase;
            margin-bottom: 1rem;
        }
        .status.fail { background: rgba(255,50,50,0.15); color: #ff6666; }
        .status.warn { background: rgba(255,170,0,0.15); color: #ffcc44; }
        .status.success { background: rgba(0,220,100,0.15); color: #44ff88; }
        .status.info { background: rgba(50,150,255,0.15); color: #66aaff; }

        .phase-card p { color: #999; margin-bottom: 0.8rem; }
        .phase-card .detail {
            background: rgba(0,0,0,0.3);
            border-radius: 8px;
            padding: 1rem;
            font-family: 'Cascadia Code', 'Fira Code', monospace;
            font-size: 0.85rem;
            color: #88cc88;
            overflow-x: auto;
            margin-top: 0.8rem;
        }
        .phase-card .error-detail {
            background: rgba(255,0,0,0.05);
            border-left: 3px solid #ff4444;
            color: #ff8888;
        }
        .phase-card .success-detail {
            background: rgba(0,255,0,0.05);
            border-left: 3px solid #00ff88;
            color: #88ffaa;
        }

        .result-section {
            max-width: 900px;
            margin: 0 auto;
            padding: 4rem 2rem;
        }
        .result-section h2 {
            text-align: center;
            font-size: 2rem;
            margin-bottom: 1rem;
            color: #fff;
        }
        .result-section .desc {
            text-align: center;
            color: #888;
            margin-bottom: 3rem;
            font-size: 1.1rem;
        }

        .protocol-box {
            background: rgba(0,100,255,0.05);
            border: 1px solid rgba(0,100,255,0.2);
            border-radius: 16px;
            padding: 2rem;
            margin-bottom: 2rem;
        }
        .protocol-box h3 { color: #66aaff; margin-bottom: 1rem; }
        .protocol-box table {
            width: 100%;
            border-collapse: collapse;
        }
        .protocol-box th, .protocol-box td {
            padding: 0.6rem 1rem;
            text-align: left;
            border-bottom: 1px solid rgba(255,255,255,0.06);
        }
        .protocol-box th {
            color: #888;
            font-weight: 600;
            font-size: 0.8rem;
            text-transform: uppercase;
        }
        .protocol-box td { font-family: monospace; }
        .protocol-box .hex { color: #ff8844; }
        .protocol-box .ascii { color: #44ddff; }
        .protocol-box .value { color: #88ff88; }

        .stats {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
            gap: 1.5rem;
            margin: 3rem 0;
        }
        .stat-card {
            background: rgba(255,255,255,0.04);
            border: 1px solid rgba(255,255,255,0.08);
            border-radius: 12px;
            padding: 1.5rem;
            text-align: center;
        }
        .stat-card .number {
            font-size: 2.5rem;
            font-weight: 800;
            background: linear-gradient(90deg, #00d4ff, #7b2fff);
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
        }
        .stat-card .label { color: #888; font-size: 0.9rem; margin-top: 0.3rem; }

        .footer {
            text-align: center;
            padding: 3rem 2rem;
            color: #555;
            border-top: 1px solid rgba(255,255,255,0.05);
        }
        .footer a { color: #6688cc; text-decoration: none; }

        @media (max-width: 600px) {
            .hero h1 { font-size: 2rem; }
            .phase { padding-left: 40px; }
            .stats { grid-template-columns: 1fr 1fr; }
        }
    </style>
</head>
<body>

<section class="hero">
    <div class="hero-content">
        <h1>ICEBERG Labs</h1>
        <p class="subtitle">
            Como hicimos ingenieria inversa a un sistema de pulseras LED chinas
            para crear nuestro propio software de programacion.
        </p>
        <div>
            <span class="tag">Reverse Engineering</span>
            <span class="tag">USB HID</span>
            <span class="tag">UART Sniffing</span>
            <span class="tag">Python</span>
            <span class="tag">ESP32</span>
            <span class="tag">Hardware Hacking</span>
        </div>
    </div>
</section>

<section class="timeline">
    <h2>La Aventura Completa</h2>

    <!-- FASE 1 -->
    <div class="phase">
        <div class="phase-dot red"></div>
        <div class="phase-card">
            <span class="status fail">Pista Falsa</span>
            <h3>Fase 1: Capturamos el trafico USB equivocado</h3>
            <p>
                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.
            </p>
            <p>
                Encontramos 591 diferencias... pero ninguna escalaba con el tiempo.
                Despues de renderizar los datos como imagen, descubrimos que eran
                <strong>tickets de la impresora 3nStar</strong>, no del programador.
            </p>
            <div class="detail error-detail">
$ python analizar_pulseras.py<br>
Diferencias encontradas: 591 bytes<br>
Bytes que escalan con tiempo: 0<br>
Conclusion: El tiempo NO esta en los datos USB... <br>
(porque estabamos viendo la impresora de recibos)
            </div>
        </div>
    </div>

    <!-- FASE 2 -->
    <div class="phase">
        <div class="phase-dot yellow"></div>
        <div class="phase-card">
            <span class="status warn">Dispositivo encontrado</span>
            <h3>Fase 2: Descubrimos que es un HID, no una impresora</h3>
            <p>
                Investigando en el Administrador de Dispositivos encontramos el programador real:
                un dispositivo HID con VID=0x1A86, PID=0xE010. El fabricante: <strong>WCH.CN</strong>,
                producto: <strong>"HID To Serial"</strong>.
            </p>
            <p>
                Escribimos un lector HID en Python y capturamos los primeros mensajes del dispositivo:
            </p>
            <div class="detail">
[IN] 06 05 46 41 49 4C 21 = "FAIL!" (sin pulsera)<br>
[IN] 04 05 4F 4B 9F = "OK" (pulsera detectada)
            </div>
            <p style="margin-top:1rem">
                Pero cuando intentamos ENVIAR comandos... el dispositivo los ignoraba todos.
                Probamos cientos de formatos: ACK, NAK, STX/ETX, ASCII, binario, checksums.
                <strong>Nada funcionaba.</strong>
            </p>
        </div>
    </div>

    <!-- FASE 3 -->
    <div class="phase">
        <div class="phase-dot yellow"></div>
        <div class="phase-card">
            <span class="status warn">Caos controlado</span>
            <h3>Fase 3: Enviamos basura y el dispositivo reacciono</h3>
            <p>
                En un test de diagnostico, enviamos bytes 0xAA repetidos para probar tamanios
                de reporte. De repente: <strong>el dispositivo sono, los LEDs cambiaron de color
                y el IR empezo a parpadear.</strong>
            </p>
            <p>
                Pero los resultados eran completamente inconsistentes. El mismo comando a veces
                hacia algo, a veces no. Probamos el header <code>AA 55</code>, y parecia un
                protocolo real, pero los resultados seguian siendo erraticos.
            </p>
            <div class="detail error-detail">
AA 55 01 = verde (a veces)<br>
AA 55 04 = azul (a veces)<br>
AA 55 06 = ciclo colores (a veces)<br>
AA 55 05 = ciclo completo (a veces nada)<br>
Consistencia: ~30% ... inaceptable
            </div>
        </div>
    </div>

    <!-- FASE 4 -->
    <div class="phase">
        <div class="phase-dot blue"></div>
        <div class="phase-card">
            <span class="status info">Punto de inflexion</span>
            <h3>Fase 4: Abrimos el programador con destornillador</h3>
            <p>
                Decidimos ir al hardware. Con un destornillador abrimos el programador y encontramos
                dos chips principales:
            </p>
            <div class="detail">
Chip 1: CH9326 (WCH) - Puente USB HID a UART<br>
Chip 2: STC 8C2K32S2 - Microcontrolador 8051<br>
Chip 3: UL26 - Regulador de voltaje<br>
Chip 4: SS14 - Diodo Schottky
            </div>
            <p style="margin-top:1rem">
                <strong>Esto lo cambio todo.</strong> 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.
            </p>
        </div>
    </div>

    <!-- FASE 5 -->
    <div class="phase">
        <div class="phase-dot blue"></div>
        <div class="phase-card">
            <span class="status info">Hardware hacking</span>
            <h3>Fase 5: Soldamos cables al UART interno con un ESP32</h3>
            <p>
                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.
            </p>
            <p>
                Hubo un momento de panico: al conectar el cable al pin TXD, <strong>el IR dejo
                de funcionar</strong>. Solucion: usar una resistencia de 10K para no cargar la linea.
            </p>
            <div class="detail">
ESP32 GPIO16 --[10K]-- CH9326 TXD (PC->MCU)<br>
ESP32 GPIO17 --------- STC TX (MCU->PC)<br>
ESP32 GND ------------ GND programador<br>
<br>
IMPORTANTE: NO usar los pines TX/RX del ESP32<br>
(esos son para Serial Monitor, GPIO 1 y 3)
            </div>
        </div>
    </div>

    <!-- FASE 6 -->
    <div class="phase">
        <div class="phase-dot green"></div>
        <div class="phase-card">
            <span class="status success">Protocolo descifrado</span>
            <h3>Fase 6: Capturamos el protocolo real por primera vez</h3>
            <p>
                Con el sniffer activo y el software original corriendo, vimos por primera vez
                los bytes REALES del protocolo:
            </p>
            <div class="detail success-detail">
[MCU->PC] 05 46 41 49 4C 21  | .FAIL! (6 bytes)<br>
[PC->MCU] 05 52 00 3C 47 00 0A 42 00 1E 44  (11 bytes)<br>
             R  60m  G  10m  B  30m  checksum<br>
<br>
El protocolo era HERMOSO en su simplicidad:<br>
[header] [R] [tiempo] [G] [tiempo] [B] [tiempo] [checksum]
            </div>
            <p style="margin-top:1rem">
                Tambien descubrimos POR QUE los comandos anteriores eran inconsistentes:
                el CH9326 usa el <strong>primer byte como longitud</strong>. Nuestro header
                <code>0x05</code> se interpretaba como "envia 5 bytes" en vez de ser parte
                del protocolo. Faltaba anteponer <code>0x0B</code> (11 bytes).
            </p>
        </div>
    </div>

    <!-- FASE 7 -->
    <div class="phase">
        <div class="phase-dot green"></div>
        <div class="phase-card">
            <span class="status success">Objetivo completado</span>
            <h3>Fase 7: Primera pulsera programada con nuestro codigo</h3>
            <p>
                Con el protocolo decodificado, creamos <code>programar_pulsera.py</code>.
                Un ultimo obstaculo: la pulsera no encendia porque el software original
                de Kpoplight seguia corriendo en segundo plano, sobreescribiendo nuestros
                tiempos con ceros.
            </p>
            <p>
                Al cerrar el software del fabricante y ejecutar solo el nuestro:
            </p>
            <div class="detail success-detail">
$ python programar_pulsera.py<br>
<br>
PROGRAMADOR DE PULSERAS LED<br>
Kpoplight Magnetic Locker Band<br>
<br>
[OK] Programador conectado<br>
<br>
Rojo=1min  Verde=1min  Azul=1min<br>
Esperando pulsera... (programadas: 0)<br>
<br>
>>> PULSERA #1 PROGRAMADA! <<<
            </div>
        </div>
    </div>
</section>

<section class="result-section">
    <h2>El Protocolo Descifrado</h2>
    <p class="desc">11 bytes que controlan todo el sistema</p>

    <div class="protocol-box">
        <h3>Formato del paquete</h3>
        <table>
            <tr>
                <th>Byte</th><th>Hex</th><th>ASCII</th><th>Funcion</th>
            </tr>
            <tr>
                <td>0</td>
                <td class="hex">05</td>
                <td class="ascii">ENQ</td>
                <td>Header fijo</td>
            </tr>
            <tr>
                <td>1</td>
                <td class="hex">52</td>
                <td class="ascii">'R'</td>
                <td>Marcador Rojo</td>
            </tr>
            <tr>
                <td>2-3</td>
                <td class="hex">00 3C</td>
                <td></td>
                <td class="value">Tiempo Rojo: 60 minutos</td>
            </tr>
            <tr>
                <td>4</td>
                <td class="hex">47</td>
                <td class="ascii">'G'</td>
                <td>Marcador Verde</td>
            </tr>
            <tr>
                <td>5-6</td>
                <td class="hex">00 0A</td>
                <td></td>
                <td class="value">Tiempo Verde: 10 minutos</td>
            </tr>
            <tr>
                <td>7</td>
                <td class="hex">42</td>
                <td class="ascii">'B'</td>
                <td>Marcador Azul</td>
            </tr>
            <tr>
                <td>8-9</td>
                <td class="hex">00 1E</td>
                <td></td>
                <td class="value">Tiempo Azul: 30 minutos</td>
            </tr>
            <tr>
                <td>10</td>
                <td class="hex">44</td>
                <td></td>
                <td>Checksum (suma & 0xFF)</td>
            </tr>
        </table>
    </div>

    <div class="stats">
        <div class="stat-card">
            <div class="number">17+</div>
            <div class="label">Scripts de prueba creados</div>
        </div>
        <div class="stat-card">
            <div class="number">256</div>
            <div class="label">Comandos probados por fuerza bruta</div>
        </div>
        <div class="stat-card">
            <div class="number">2</div>
            <div class="label">Chips identificados en el PCB</div>
        </div>
        <div class="stat-card">
            <div class="number">11</div>
            <div class="label">Bytes del protocolo final</div>
        </div>
        <div class="stat-card">
            <div class="number">9600</div>
            <div class="label">Baud rate del UART interno</div>
        </div>
        <div class="stat-card">
            <div class="number">1</div>
            <div class="label">Dia para descifrarlo todo</div>
        </div>
    </div>
</section>

<section class="result-section">
    <h2>Proxima Fase</h2>
    <p class="desc">Sistema propio de gestion para ICEBERG</p>
    <div class="protocol-box" style="border-color: rgba(255,0,128,0.2); background: rgba(255,0,128,0.03);">
        <h3 style="color: #ff4488;">En desarrollo</h3>
        <p style="color:#999; line-height: 2;">
            Interfaz web para programar pulseras desde cualquier dispositivo<br>
            Integracion con sistema de venta y cobro<br>
            Panel de administracion con reportes y estadisticas<br>
            Historial de pulseras programadas<br>
            Configuracion de paquetes y precios por color/tiempo<br>
            100% independiente del software chino
        </p>
    </div>
</section>

<footer class="footer">
    <p>
        ICEBERG Labs &mdash; Quito, Ecuador &mdash; <?php echo date('Y'); ?><br>
        <small>Ingenieria inversa realizada con <a href="https://claude.ai">Claude</a> + Python + ESP32 + un destornillador</small>
    </p>
</footer>

</body>
</html>
