2 Punkte von GN⁺ 2023-12-16 | 1 Kommentare | Auf WhatsApp teilen
  • Beim Reverse Engineering, um günstige Bluetooth LE-LED-Leuchten an Home Assistant anzubinden, wurde beim Testen versteckter Effektwerte eines 10-m-Strings mit adressierbaren LEDs der Controller unbrauchbar
  • Mit Bluetooth HCI snoop unter Android und Wireshark/tshark wurden die BLE-Pakete aufgezeichnet, die die App an die Beleuchtung sendet, und in Schreibanforderungen mit btatt.opcode.method==0x12 die Steuerbytes nachverfolgt
  • Die Pakete der iDeal-LED-App sahen nicht wie einfache Ein/Aus-Werte aus; nach dem Dekompilieren der APK und einem vorhandenen Analyseartikel wurden sie mit einem festen AES-Schlüssel aus libAES.so entschlüsselt
  • Die entschlüsselten Ein/Aus-Pakete ließen sich auf einen festen Header und den Unterschied 1/0 im fünften Byte zurückführen; durch wiederholtes Ausführen von Farb-, Helligkeits- und Effektfunktionen wurden die Bytemuster protokolliert
  • Als statt des von der App verwendeten 5-Bit-Bereichs 0x1F bei RGB 8-Bit-Werte gesendet wurden, waren hellere Farben möglich, doch beim Senden der Effektnummer 12 ging das Licht aus und auch die Bluetooth-Werbung verschwand

Ausgangspunkt: günstige BLE-Leuchten in die Heimautomatisierung einbinden

  • Ausgehend von der Annahme, dass sich Geräte, die über Bluetooth LE kommunizieren und eine eigene App haben, in Heimautomatisierungssysteme integrieren lassen, wurden mehrere günstige LED-Streifen per Reverse Engineering untersucht
  • Zuvor wurde ein 5-m-LED-Streifen ohne adressierbare LEDs mit Bluetooth-LE-Steuerung für 2,38 £ innerhalb weniger Stunden mit Home Assistant verbunden; der zugehörige Code ist als bj_led veröffentlicht
  • Reverse Engineering zum LEDnetWF-Controller gibt es ebenfalls unter lednetwf_ble
  • Diesmal ging es um einen 10-m-String mit adressierbaren LEDs auf dem Schreibtisch, der mit der App „iDeal LED“ gesteuert wird
    • Die App bietet viele Funktionen und arbeitet vergleichsweise gut
    • Bei den LEDs könnte es sich um WS2812 oder ein ähnliches Produkt handeln
    • Das Produkt ist eine bei AliExpress gekaufte Beleuchtung

Die von der App gesendeten BLE-Bytes erfassen

  • Um das Gerät mit eigener Software zu steuern, muss man zuerst die Bytefolge sehen, die die App per Bluetooth an das Gerät sendet
  • Ein typisches Beleuchtungsprotokoll kann aus einem Header, Befehlsbytes für Ein/Aus oder Farbwechsel und einem Footer bestehen, der eine Prüfsumme sein könnte
  • Unter Android wurde die Erfassung so durchgeführt
    • den Entwicklermodus aktivieren
    • die Beleuchtungs-App installieren
    • in den Entwickleroptionen Bluetooth HCI snoop einschalten
    • in der App Aktionen wie Ein- und Ausschalten der Beleuchtung ausführen
    • das Log mit adb pull sdcard/btsnoop_hci.log . auf den Computer kopieren
  • Öffnet man das Log in Wireshark, sieht man die an die Beleuchtung gesendeten Bytes
    • ein Beispielfilter ist bluetooth.dst == ff:ff:ff:ff:ff:ff && btatt.opcode.method==0x12
    • die MAC-Adresse muss durch die tatsächliche MAC der Beleuchtung ersetzt werden
    • btatt.opcode.method==0x12 bedeutet, dass vom Android-Gerät ein Schreibvorgang an die Beleuchtung stattgefunden hat
  • Mit tshark lassen sich die Paketwerte direkt im Terminal ausgeben
    • tshark -r <filename> -T fields -e btatt.value gibt die an den LED-Controller geschriebenen Payloads aus

Warum einfaches Replay beim iDeal-LED-Protokoll nicht ausreichte

  • Bei manchen Leuchten ist bei Ein/Aus-Vorgängen ein fast direkt lesbares Muster zu erkennen
    • ein Beispiel ist eine Wiederholung von 69 96 02 01 01 und 69 96 02 01 00
    • das letzte Byte wechselt zwischen 1 und 0 und steht für Ein und Aus
  • Bei dieser iDeal-LED-Beleuchtung wurden deutlich längere Bytefolgen wiederholt; die beiden zu Ein/Aus gehörenden Pakete ließen sich zwar unterscheiden, die Werte sahen jedoch wie Rauschen aus
  • Wenn es nur um Ein- und Ausschalten geht, kann ein Replay ausreichen, bei dem die aufgezeichnete Bytefolge unverändert erneut gesendet wird
    • mit gatttool lassen sich Bytes an ein BLE-Gerät senden
    • den zu beschreibenden Handle muss man in Wireshark nachsehen
  • Für mehr Kontrolle musste die Paketstruktur verstanden werden, daher ging es als Nächstes an die Analyse der Android-App selbst

APK dekompilieren und den AES-Schlüssel finden

  • Die APK wurde heruntergeladen, mit jadx geöffnet und der App-Code untersucht
  • Im Quelltext fanden sich Verweise auf AES, was den Verdacht nahelegte, dass das Protokoll verschlüsselt ist
  • Für die verschlüsselten Daten wurden folgende Annahmen getroffen
    • der Chiffretext derselben Aktion ändert sich nicht jedes Mal, also könnte es einen konsistenten Schlüssel geben
    • auf einem stromsparenden MCU muss die Entschlüsselung schnell erfolgen, daher ist ein kurzer Schlüssel vorteilhaft
    • der Schlüssel könnte nicht pro Gerät individuell, sondern fest vorgegeben sein
  • Die App enthielt eine kompilierte AES-Bibliothek namens libAES.so, die sich mit jadx allein nicht analysieren ließ
  • Es wurde ein Analyseartikel gefunden, in dem jemand die AES-Bibliothek mit ida free dekompiliert und den eingebetteten Schlüssel gefunden hatte; dieser Schlüssel wurde getestet
  • Mit dem ECB-Modus von AES aus Crypto.Cipher ließen sich die Pakete entschlüsseln, und die Ein/Aus-Pakete nahmen eine sinnvolle Form an
    • die entschlüsselten Werte erschienen als 05 54 55 52 4E 01 ... und 05 54 55 52 4E 00 ...
    • nach einem festen Header wechselt das fünfte Byte zwischen 1 und 0 und steht für Ein und Aus
    • der Rest ist mit Nullen aufgefüllt
  • Ab diesem Punkt konnten die von der App gesendeten Pakete entschlüsselt und dieselbe Steuerung im eigenen Code nachgebildet werden

Bytemuster für einzelne Funktionen protokollieren

  • Der Protokollumfang wurde erweitert, indem jede Funktion der App einzeln ausgeführt und die gesendeten Bytes protokolliert wurden
  • Jede Aktion wurde mehrfach wiederholt, und zur Abgrenzung der Abschnitte wurde zwischendurch ein Aus/Ein-Muster eingefügt
    • die Farbe wurde mehrfach in der Reihenfolge Rot, Grün, Blau geändert
    • die Helligkeit wurde auf 100 %, 50 %, 10 %, 50 %, 100 % geändert
    • zwischen den Gruppen wurde Aus/Ein eingefügt, damit sich die Grenzen im Capture-Log leichter erkennen lassen
  • So ließ sich nachvollziehen, welche Bytes sich je nach Aktion ändern, und die protokollierten Aktionen konnten den aufgezeichneten Paketen zugeordnet werden

Effektnummer 12, die den Controller gebrickt hat

  • Bei der Untersuchung der Farbänderung zeigte sich, dass die App für Rot-, Grün- und Blauwerte nichts Größeres als 0x1F sendet
    • 0x1F ist ein 5-Bit-Bereich
    • wurden direkt 8-Bit-Werte gesendet, funktionierten hellere Farben
  • Um zu prüfen, ob es neben den 10 von der App verwendeten Effekten weitere gibt, wurde eine range(20)-Schleife ausgeführt, die Effektnummern nacheinander sendet
    • 1 bis 10 funktionierten normal
    • bei 11 wurde ein Verhalten entdeckt, das wie ein versteckter Modus wirkte
    • beim Übergang zu 12 ging die Beleuchtung aus
  • Danach ließ sich die Beleuchtung nicht mehr einschalten
    • sie sendete keine Bluetooth-Werbung mehr
    • eine Verbindung war nicht mehr möglich
    • auch beim Einschalten mit gedrückter Taste ließ sie sich nicht wiederherstellen
    • selbst nach einer Nacht ohne Strom kam sie nicht zurück
  • Als mögliche Ursache wurde ein Buffer Overflow vermutet, der die Firmware beschädigt hat, sicher festgestellt wurde die Ursache aber nicht
  • Die LEDs selbst sind Standard-LEDs mit Adressierung und können durch Anschluss an einen anderen Mikrocontroller weiterverwendet werden

Was bleibt und worauf man achten sollte

  • Trotz des Fehlschlags wurde der Großteil des Protokolls dokumentiert, und es entstand ein GitHub-Projekt mit einer Home-Assistant-Custom-Component
  • Die Komponente funktioniert, aber ähnliche Experimente können den Beleuchtungs-Controller beschädigen und sollten daher auf eigenes Risiko durchgeführt werden

1 Kommentare

 
GN⁺ 2023-12-16
Hacker-News-Kommentare
  • Es sieht weniger nach einem „festen Header“ von FTA aus, sondern eher nach einem Längenbyte („Befehl ist 5 Byte“), dem Befehl TURN, einem Argument 0/1 und dann Nullen zum Auffüllen auf 16 Byte.

    • 54 55 52 4E fällt sofort als Großbuchstabenfolge TURN auf.
      Wenn man weiß, dass Ziffern bei 0x30, Großbuchstaben bei 0x41 und Kleinbuchstaben bei 0x61 beginnen, findet man alphanumerische Muster in einem Hex-Dump leichter.
      Bei kurzen Strings ist dieses Wissen nützlich, aber wenn man Pakete oder Memory-Dumps ansieht, ist das Standard-Hexdump-Format am besten.
    • Gut erkannt. 0x54 55 52 4E ist tatsächlich T U R N.
    • Guter Fund. Ich werde auch andere Befehle prüfen, um zu sehen, ob die Längenbyte-Hypothese stimmt; sie wirkt plausibel.
    • Es ist sehr wahrscheinlich kein Padding, sondern einfach ein uint.
    • In diesem Fall ist der Header bezogen auf Länge und Startposition gewissermaßen fest.
  • Es könnte ein Problem mit der Stromversorgung sein. Die WS281x-Serie kann sehr hell leuchten, und wenn man mehrere davon kombiniert, ziehen sie enorm viel Strom.
    Bei einem Strip mit 100 LEDs und einem 12V-3A-Netzteil reicht es gerade so, alles mit maximaler Helligkeit in Weiß zu betreiben, und das ist sehr blendend.
    Deshalb würde ich zuerst nach einer durchgebrannten Sicherung schauen. Dass die Firmware von maximal 255 Helligkeitsstufen nur bis 31 nutzt, ist ebenfalls ein Hinweis.

    • Als ich gesehen habe, dass die Helligkeit auf 0x1f begrenzt ist, dachte ich zuerst auch daran. Mit etwas Glück hat das Netzteil eine Sicherung, und nur die Sicherung ist durchgebrannt.
      Selbst wenn es sich nicht retten lässt: Ein standardmäßiger WS281x-LED-String kann an einen Raspberry Pi angeschlossen werden, und man kann auch meinen Open-Source-Controller für adressierbare LEDs verwenden :) https://github.com/mbevand/ledthemfight
      Er hat eingebaute Effekte und ist für DIY sehr modular aufgebaut, sodass man mit zwei Zeilen Python ein einfaches Custom-LED-Effektmodul erstellen kann. Demo hier: https://youtu.be/qpd2rILsnM4
    • Gute Idee. Ich hole mal das Multimeter heraus.
    • Das sieht nicht nach WS2812 aus. Dem verlinkten Ali-Angebot zufolge hat der Strip vier Leitungen: 12V, Rot, Grün und Blau.
      Das wirkt eher wie ein analoger RGB-Strip, bei dem der gesamte Strip in derselben Farbe leuchtet, nicht wie einzeln adressierbare LEDs.
      https://www.aliexpress.com/item/1005005485885067.html
      Wer mit LED-Beleuchtung herumspielen will, sollte sich unbedingt WLED ansehen. Es hat viele eingebaute Effekte, eine Web-GUI, nutzt sehr günstige ESP32 oder ESP8266 als Controller und kann auch auf Sound reagieren. Ich lasse WLED gerade auf meiner Indoor-Weihnachtsbeleuchtung laufen, und es sieht richtig gut aus.
    • Danke für den Tipp. Ich habe den Code aktualisiert, sodass er um 3 Bit nach rechts schiebt und wieder zu einer 5-Bit-Zahl zurückkehrt.
      Das ist eine saubere Methode, den Stromverbrauch zu begrenzen.
  • Guter Artikel. Ich erinnere mich daran, dass ich versucht habe, meine Leuchten zu reverse-engineeren, und dann feststellte, dass sie verschlüsselt sind.
    Eine war eine amaran 60d, die anderen waren ein paar SmallRig-RM75-Akku-LED-Leuchten; ich wollte alle mit einem Skript ein- und ausschalten, ohne zwei verschiedene Apps bedienen zu müssen.
    Ich habe ziemlich viel Zeit damit verbracht, die Apps und Protokolle zu reverse-engineeren, und beide Leuchten nutzten offenbar denselben Aushandlungsprozess, waren aber wohl mit unterschiedlichen Bibliotheken implementiert.
    Ich versuchte, den beim Verbindungsaufbau durchgeführten Diffie-Hellman-Schlüsselaustausch nachzuahmen, gab aber schließlich auf. Soweit ich mich erinnere, gab es danach noch ein oder zwei weitere Schritte, und nach dem Senden des ersten Schlüssels wurde noch eine zufällig wirkende Zahl (ein weiterer Schlüssel?) gesendet; ich konnte nicht herausfinden, was dort erwartet wurde.
    Dieser Artikel bringt mich auf die Idee, einfach mal einen hartcodierten Schlüssel einzusetzen und zu prüfen, ob es funktioniert.

    • Es wäre wirklich großartig, wenn das bei Amaran-Leuchten klappt. Dann könnte das vermutlich zum Reverse Engineering der gesamten Aputure-Produktlinie führen.
      Eine Open-Source-Integration für Elgato Stream Deck oder Home Assistant wäre wohl ein großer Erfolg. Für YouTube-Leute, die Talking-Head-Videos am Schreibtisch aufnehmen, wäre das viel besser, als die Beleuchtung per Smartphone-App zu steuern.
  • Beim Versuch, BLE-verbundene Weihnachtsbeleuchtung zu automatisieren, habe ich Elektroschrott erzeugt. Jetzt kannst du das auch.

    • Ich weiß nicht, wie du es gemacht hast, aber ich habe gesehen, dass manche dieser SmartTrash-Geräte durch eine magische Sequenz wie fünfmal schnelles Aus- und Einschalten hart zurückgesetzt werden.
    • Wenn du BLE-Packet-Sniffing GUI-orientierter machen willst, probier die App nRF Connect aus.
      Beim iPhone weiß ich es nicht, aber unter Android kann man sie im Hintergrund laufen lassen und BLE-Aktivitäten über die aufgeräumte GUI des Telefons erfassen. Ich nutze sie täglich.
    • Wenn man den Controller umgeht, kann man sie immer noch als dumme/klassische Beleuchtung verwenden.
  • Das erinnert mich an Tastatur-MCUs, die gebrickt wurden, wenn sie einen bestimmten Beleuchtungsbefehl erhielten.
    OpenRGB musste schließlich deaktivieren, dass dieses Modul auf der betreffenden Hardware automatisch ausgeführt wird. Manchmal löste auch die Herstellersoftware denselben Bug aus.
    Leider musste man normalerweise einen USB-HID-Report senden, um in den In-System-Programming-Modus zu gelangen, aber die betroffenen Geräte wurden nicht einmal mehr enumeriert.
    Ob es tatsächlich eine Firmware-Beschädigung war oder die Hardware durch ein anderes undefiniertes Verhalten beschädigt wurde, ist eine separate Frage.

  • „Wenn man Klartext drahtlos sendet, ist das doch unsicher.“
    „Keine Sorge, wir haben AES-Verschlüsselung eingebaut.“

    • Tuya ist in dieser Hinsicht wirklich komisch. Das Protokoll ist einfach TLS über TCP, aber jedes Mal, wenn die App ein neues Gerät hinzufügt, streut sie das WLAN-Passwort an alle STAs in der Umgebung heraus.
      So funktioniert nämlich das Pairing. Die App broadcastet blind Pakete an 255.255.255.255, und das Zielgerät (Glühbirne, Steckdose usw.) wartet im Promiscuous Mode.
      Der Paketinhalt ist zwar durch WPA2 o. Ä. geschützt, aber die Paketlänge nicht. Deshalb werden Unmengen winziger Pakete gesendet, deren jeweilige Länge auf den ASCII-Bytewert des nächsten Zeichens im Setup-Handshake gesetzt ist. Vermutlich wird das mehrfach wiederholt.
      Daher dauert das Pairing zwei Minuten und bricht immer plötzlich ab, bevor der Zähler 0 erreicht.
    • Klingt nach Verschlüsselung gegen die Luft.
  • Genau das hat mir letztes Jahr wirklich Sorgen gemacht, als ich den BLE-Controller meines Kamins reverse-engineert habe.
    Insbesondere der Befehl „Set password“ nimmt rohe Byte-Eingaben entgegen, während die OEM-App nur längenbegrenzte numerische Daten gesendet hat.
    Zum Glück schien er nach einem kurzen Stromausfall alles zu vergessen, was zuvor passiert war.
    Deshalb scheinen die meisten BLE-Controller derselben Marke einfach beim Standardpasswort 0000 zu bleiben. Nach einem Stromausfall landen sie letztlich wieder in diesem Zustand. Wenn einem wirklich langweilig ist, wäre das ein ziemlich gutes Thema für BLE-Wardriving.
    Ich habe meine Reverse-Engineering-Ergebnisse auch in eine Home-Assistant-Integration gegossen (https://github.com/kaechele/napoleon-efire) und außerdem Dokumentation zu System und Protokoll geschrieben (https://bonaparte.readthedocs.io/en/latest/index.html).

  • Ich suche nach flexibler und robuster Beleuchtung für einen Dachträger am Auto.
    Sie soll batteriebetrieben und für draußen bzw. jedes Wetter geeignet sein; ideal wäre, wenn sich die Batteriebox mit Kabelbindern leicht an einer Oberfläche befestigen ließe.
    Möglichst im „Mini“-Formfaktor T5, mit RGB und programmierbar, damit ich sie saisonal nutzen kann: Rot/Grün zu Weihnachten, Lila/Orange zu Halloween usw.
    Ich frage mich, ob jemand ein Produkt kennt, das diese Anforderungen erfüllt. Die ersten drei Bedingungen findet man bei Walmart oder Home Depot, aber etwas zu finden, das auch die letzte erfüllt, war schwierig.
    Bei der Suche kommt nur jede Menge Rauschen heraus.
    [1] https://cdn.christmaslightsetc.com/images/CategoryDetail/788...

    • Es hängt wohl davon ab, wie viel DIY du machen möchtest.
      Zum Beispiel sind 12V-LED-Strips mit IP67-Wasserschutz (in einem Silikonschlauch) leicht zu bekommen [0], und weil sie viel mehr LEDs haben als eine Lichterkette im Weihnachtsbeleuchtungsstil, wäre der Effekt auch deutlich stärker.
      Allerdings müsstest du einen Mikrocontroller wie Arduino, ESP32 oder ESP8266 kaufen und programmieren und selbst lösen, wie du den Strom aus der Autobatterie holst [1].
      Die Elektronik könntest du im Auto unterbringen und nur die Kabel aus dem Kofferraum herausführen; eventuell reicht dann die vorhandene Kofferraumdichtung als Wetterschutz.
      [0] https://www.aliexpress.com/item/1005004289391906.html
      [1] https://www.aliexpress.com/item/1005005977505151.html
    • Du könntest dir auch WS2811 im „bullet string“-Stil ansehen. Wenn du sie an 12V im Auto anschließen willst, sind sie nativ 12V, kommen normalerweise als wasserdichte Produkte mit xConnect-Pigtails, sind einfach zu befestigen und flexibel.
      Sie lassen sich auch leicht mit Verlängerungskabeln neu verlöten oder in Reihe schalten.
      https://www.aliexpress.com/item/4000105913323.html
      Soweit ich gelesen habe, scheinen solche Produkte oder ähnliche 5V-Leuchten bei Outdoor-Weihnachtslichtshows so etwas wie Standard zu sein.
    • Geh auf den WLED-Discord und schau dir die Kanäle #projects und #showcase an. Dort gibt es viele Projekte mit RGB-LED-Beleuchtung an Fahrzeugen.
      Aber Vorsicht: In dieses Thema kann man leicht hineingezogen werden.
      Einladungslink: https://discord.gg/eVhhh2Wh
  • Könnte man sehen, wie die kaputte Weihnachtsbeleuchtung zerlegt aussieht?
    Wenn man weiß, welcher Chip darin steckt, könnte das Hinweise darauf geben, ob Flash-Speicher vorhanden ist und wie leicht er sich dumpen lässt.