Für dieses Projekt habe ich die „C by GE“-App zur Steuerung der über WLAN verbundenen intelligenten Glühbirnen von GE rückentwickelt. Dazu habe ich zunächst die Android-App dekompiliert und dann das Binärprotokoll, das die App für die Kommunikation mit einem Server verwendet, rückentwickelt. Weitere Einzelheiten finden Sie unter Reverse Engineering C von GE.
Die Endprodukte dieses Projekts sind:
Haftungsausschluss: Dieser Code ist das Ergebnis eines Reverse Engineering und wurde nicht durch eine Protokollspezifikation informiert. Daher gibt es keine Garantie dafür, dass es weiterhin funktioniert oder dass es für jedes Netzwerk oder Smart-Gerät funktioniert. Während andere diese API in einigen Fällen erfolgreich verwendet haben, ist es möglich, dass der Code falsche Annahmen trifft, die nicht in jedem Anwendungsfall Bestand haben.
Das Serververzeichnis ist eine eigenständige Web-App und ein JSON-API-Endpunkt für C by GE-Glühbirnen. Die Website sieht so aus:
Wenn Sie die Website mit den Argumenten -email
und -password
ausführen, öffnet die Website beim ersten Laden eine Zwei-Faktor-Authentifizierungsseite. Sie klicken auf eine Schaltfläche und geben den an Ihre E-Mail-Adresse gesendeten Bestätigungscode ein. Alternativ können Sie sich vorab anmelden, indem Sie den Befehl login_2fa ausführen und dabei die Flags -email
und -password
auf Ihre Kontoinformationen setzen. Der Befehl fordert Sie zur Eingabe des 2FA-Bestätigungscodes auf. Sobald Sie diesen Code eingeben, gibt der Befehl Sitzungsinformationen als JSON-Blob aus. Sie können diesen JSON dann an das Argument -sessinfo
des Servers übergeben, z. B. als -sessinfo 'JSON HERE'
. Beachten Sie, dass ein Teil der Sitzung nach einer Woche abläuft, eine laufende Serverinstanz jedoch nach dieser Zeit weiterhin funktioniert, da der ablaufende Teil der Sitzung nur einmal zum Aufzählen von Geräten verwendet wird.
Neuere Konten erfordern die Verwendung einer Zwei-Faktor-Authentifizierung. Sie können einen 2FA-Handshake durchführen, um eine Sitzung wie folgt zu erstellen:
callback , err := cbyge . Login2FA ( "my_email" , "my_password" , "" )
// Handle error...
sessionInfo , err := callback ( "2FA code from email" )
// Handle error...
session , err := cbyge . NewController ( sessionInfo , 0 )
// Handle error...
Bei älteren Konten, die noch nie 2FA verwendet haben, können Sie sich möglicherweise direkt anmelden:
session , err := cbyge . NewControllerLogin ( "my_email" , "my_password" )
// Handle error...
Sobald Sie eine Sitzung haben, können Sie Geräte wie folgt auflisten:
devs , err := session . Devices ()
// Handle error...
for _ , x := range devs {
fmt . Println ( x . Name ())
}
Sie können Glühbirnen wie folgt steuern:
x := devs [ 0 ]
session . SetDeviceStatus ( x , true ) // turn on
session . SetDeviceLum ( x , 50 ) // set brightness
session . SetDeviceCT ( x , 100 ) // set color tone (100=blue, 0=orange)
Sie können auch die aktuellen Einstellungen einer Glühbirne abfragen:
status , err := session . DeviceStatus ( x )
// Handle error...
fmt . Println ( status . IsOn )
fmt . Println ( status . ColorTone )
In diesem Abschnitt erkläre ich Ihnen, wie ich Teile des C by GE-Protokolls rückentwickelt habe.
Der erste Schritt bestand darin, die Android-App mit Apktool zu zerlegen. Dies führt zu einer Smali-Demontage für die App. Ich stöberte herum und suchte nach URLs und Domänennamen. Zunächst habe ich Folgendes gefunden:
.field public static final API_VERSION : L java/lang/String ; = " v2/ "
.field public static final BASE_URL : L java/lang/String ; = " https://api-ge.xlink.cn:443/ "
Als ich sah, wo dieser API-Endpunkt verwendet wurde, gelangte ich schnell zu einer Reihe von JSON-basierten HTTP-Aufrufen zum Anmelden, Auflisten von Geräten usw. Dieser Endpunkt schien jedoch keine Möglichkeit zu bieten, 1) den Status von Geräten abzurufen oder 2) Aktualisieren Sie die Farbe oder Helligkeit der Geräte.
Es musste eine andere Möglichkeit geben, wie die App mit den intelligenten Glühbirnen kommunizierte. Allerdings war die Demontage mit Code für die Bluetooth- und LAN-Kommunikation übersät, und ich hatte ein wenig Angst, dass es keinen globalen API-Endpunkt zur Steuerung der Glühbirnen gab . Was noch schlimmer war: Die C by GE-App beschwerte sich jedes Mal, wenn ich Bluetooth ausschaltete und dann versuchte, es zu verwenden. Irgendwann habe ich jedoch herausgefunden, dass ich die App öffnen, sie tun lassen und dann Bluetooth und WLAN ausschalten kann, während ich weiterhin die Kontrolle über die Glühbirnen habe. Alles, was ich tun musste, war auf die Android-Schaltfläche „Zurück“ zu klicken, wann immer die App ein Popup öffnete, in dem ich aufgefordert wurde, „Standortverfolgung zu aktivieren“ (wohlgemerkt ein seltsamer Name für Bluetooth und WLAN).
Zu diesem Zeitpunkt war ich mir ziemlich sicher, dass die App keine anderen mysteriösen HTTP(S)-Verbindungen herstellte. Interessanterweise habe ich die Domain „xlink.cn“ jedoch an anderer Stelle im Smali-Code gefunden:
.field public static final CM_SERVER_ADDRESS : L java/lang/String ; = " cm-ge.xlink.cn "
.field public static final CM_SERVER_PORT : I = 0x5ce2
Heilige Kuh, könnte das ein Raw-Socket-basiertes Protokoll sein? Ich habe es versucht und tatsächlich konnte ich eine TCP-Verbindung zu cm-ge.xlink.cn:23778
öffnen. Allerdings war Smali auch mit Logik für UDP -Pakete gespickt, sodass ich nicht sicher war, welches Protokoll die App verwenden würde. Vor diesem Hintergrund habe ich einen Paket-Proxy erstellt und ihn auf Port 23778 überwacht. Dann habe ich die Domäne cm-ge.xlink.cn
durch meine IP-Adresse im Smali-Code ersetzt, die App in ein APK neu kompiliert und installiert mein Telefon.
Tatsächlich stellte meine gepatchte C by GE-App sofort eine Verbindung zu meiner Paket-Proxy-Instanz her und begann mit dem Chatten. Dies geschah insbesondere nur, wenn Bluetooth und WLAN ausgeschaltet waren. Ansonsten schien es eines davon zu bevorzugen, um lokal mit den intelligenten Glühbirnen zu kommunizieren.
Das von der App gewählte Protokoll war bei weitem am einfachsten zu handhaben: 1) Es war TCP statt UDP, 2) es war völlig unverschlüsselt. Im Nachhinein ist die fehlende Verschlüsselung ziemlich alarmierend, da die erste Nachricht ein Autorisierungstoken enthält, das sich für mein Konto nie zu ändern scheint.
Ich habe festgestellt, dass die Nachrichten von der App an den Server effektiv „wiedergegeben“ werden können. Nachdem ich herausgefunden hatte, welche Bytes (oder „Pakete“, dank Paket-Proxy) zum Ein- und Ausschalten von Lichtern dienten, konnte ich einfach einen neuen Socket öffnen und dieselben Pakete senden und die gleichen Ergebnisse erzielen. Das war ein tolles Zeichen. Im schlimmsten Fall hatte ich bereits eine Möglichkeit, das, was ich wollte, für mich selbst umzusetzen, auch wenn es nicht sehr allgemein wäre.
An diesem Punkt war es an der Zeit, tiefer in das Protokoll einzusteigen. Nach einer Kombination aus Experimenten mit Paket-Proxy und einer Auseinandersetzung mit der Smali-Disassemblierung hatte ich ein ziemlich allgemeines Verständnis davon, welche Kommunikation stattfand. Das erste, was mir auffiel, war, dass die Kommunikation in „Nachrichten“ stattfand, die mit einem Typ- und einem Längenfeld (in Big Endian) begannen. Als nächstes musste herausgefunden werden, welche Pakettypen wo welche waren und schließlich, wie die spezifischen Pakete selbst kodiert waren. Hier ist ein Beispiel für ein Paket vom Server, das den Status meiner drei Geräte enthält:
73 00 00 00 60 47 e2 be ab 00 37 00 7e 00 01 00 00 f9 52 4e
00 03 00 00 00 03 00 03 00 81 01 00 00 81 01 00 00 00 00 35
00 00 00 27 00 00 00 00 00 00 00 02 00 00 01 00 00 00 01 00
00 00 00 35 00 00 00 27 00 00 00 00 00 00 00 01 00 00 01 00
00 00 01 00 00 00 00 35 00 00 00 27 00 00 00 00 00 00 00 c8
7e
Nachdem ich genug von dem Protokoll ausgearbeitet hatte, erstellte ich eine API dafür. Diese API kann Geräte auflisten, ihren Status abrufen und verschiedene Eigenschaften der Geräte aktualisieren (z. B. Helligkeit und Farbton). Überraschenderweise war meine API viel schneller und zuverlässiger als die App selbst. Es scheint, dass der Versuch, Bluetooth oder WLAN zu verwenden, bevor auf einen Remote-Server zurückgegriffen wird, dazu führt, dass die App viel unsicherer und weniger zuverlässig ist, als sie sein könnte.
Abschließend möchte ich sagen, dass ich nicht alle von dieser App unterstützten Geräte besitze und daher weder motiviert (oder leicht dazu in der Lage) war, die Funktionsweise dieser Geräte zurückzuentwickeln. Dasselbe Unternehmen stellt beispielsweise intelligente Steckdosen, Sensoren und Lichtschalter her.