Para este proyecto, realicé ingeniería inversa en la aplicación "C by GE" para controlar bombillas inteligentes conectadas a WiFi de GE. Para hacer esto, comencé descompilando la aplicación de Android y luego realicé ingeniería inversa en el protocolo binario que utiliza la aplicación para comunicarse con un servidor. Para obtener más detalles, consulte Ingeniería inversa C de GE.
Los productos finales de este proyecto son:
Descargo de responsabilidad: este código es el resultado de ingeniería inversa y no ha sido informado por una especificación de protocolo. Como resultado, no hay garantía de que seguirá funcionando o de que funcionará para todas las redes o dispositivos inteligentes. Si bien otros han utilizado esta API con éxito en algunos casos, es posible que el código haga suposiciones incorrectas que no se sostienen en todos los casos de uso.
El directorio del servidor es una aplicación web autónoma y un punto final API JSON para bombillas C de GE. El sitio web se ve así:
Si ejecuta el sitio web con un argumento -email
y -password
, el sitio web mostrará una página de autenticación de dos factores la primera vez que lo cargue. Presionarás un botón e ingresarás el código de verificación enviado a tu correo electrónico. Alternativamente, puede iniciar sesión con anticipación ejecutando el comando login_2fa con los indicadores -email
y -password
configurados con la información de su cuenta. El comando le solicitará el código de verificación 2FA. Una vez que ingrese este código, el comando generará información de la sesión como un blob JSON. Luego puede pasar este JSON al argumento -sessinfo
del servidor, por ejemplo, como -sessinfo 'JSON HERE'
. Tenga en cuenta que parte de la sesión vence después de una semana, pero una instancia de servidor en ejecución seguirá funcionando después de este tiempo, ya que la parte vencible de la sesión solo se usa una vez para enumerar dispositivos.
Las cuentas más nuevas requieren el uso de autenticación de dos factores. Puede realizar un protocolo de enlace 2FA para crear una sesión de esta manera:
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...
Para cuentas más antiguas que nunca antes han usado 2FA, es posible que puedas iniciar sesión directamente:
session , err := cbyge . NewControllerLogin ( "my_email" , "my_password" )
// Handle error...
Una vez que tenga una sesión, puede enumerar dispositivos de esta manera:
devs , err := session . Devices ()
// Handle error...
for _ , x := range devs {
fmt . Println ( x . Name ())
}
Puedes controlar las bombillas así:
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)
También puedes consultar la configuración actual de una bombilla:
status , err := session . DeviceStatus ( x )
// Handle error...
fmt . Println ( status . IsOn )
fmt . Println ( status . ColorTone )
En esta sección, le explicaré cómo realicé ingeniería inversa en partes del protocolo C by GE.
El primer paso fue desmontar la aplicación de Android con Apktool. Esto produce un pequeño desmontaje de la aplicación. Husmeando, busqué URL y nombres de dominio. Inicialmente encontré esto:
.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/ "
Ver dónde se usaba este punto final API me llevó rápidamente a un conjunto de llamadas HTTP basadas en JSON para iniciar sesión, enumerar dispositivos, etc. Sin embargo, este punto final no parecía proporcionar una manera de 1) obtener el estado de los dispositivos, o 2) actualizar el color o brillo de los dispositivos.
Tenía que haber alguna otra forma en que la aplicación se comunicara con las bombillas inteligentes. Sin embargo, el desmontaje estuvo plagado de código para la comunicación Bluetooth y LAN, y me preocupaba un poco que no hubiera un punto final API global para controlar las bombillas. Lo que era peor, la aplicación C by GE se quejaba cada vez que apagaba el Bluetooth y luego intentaba usarlo. Sin embargo, finalmente descubrí que podía abrir la aplicación, dejar que hiciera su trabajo y luego apagar Bluetooth y WiFi sin dejar de tener control sobre las bombillas. Todo lo que tenía que hacer era presionar el botón "atrás" de Android cada vez que la aplicación abría una ventana emergente que me pedía "Activar el seguimiento de ubicación" (un nombre extraño para Bluetooth y WiFi, claro está).
En este punto, estaba bastante seguro de que la aplicación no estaba realizando otras conexiones HTTP(S) misteriosas. Curiosamente, encontré el dominio "xlink.cn" en otra parte del código Smali:
.field public static final CM_SERVER_ADDRESS : L java/lang/String ; = " cm-ge.xlink.cn "
.field public static final CM_SERVER_PORT : I = 0x5ce2
Dios mío, ¿podría ser este un protocolo basado en sockets sin formato? Lo intenté y, efectivamente, pude abrir una conexión TCP a cm-ge.xlink.cn:23778
. Sin embargo, Smali también estaba plagado de lógica para paquetes UDP , por lo que no estaba seguro de qué protocolo usaría la aplicación. Con esto en mente, creé paquete-proxy y lo configuré escuchando en el puerto 23778. Luego reemplacé el dominio cm-ge.xlink.cn
con mi dirección IP en el código Smali, recopilé la aplicación en un APK y la instalé en mi teléfono.
Seguramente, mi aplicación C by GE parcheada se conectó inmediatamente a mi instancia de proxy de paquetes y comenzó a conversar. En particular, solo hizo esto cuando Bluetooth y WiFi estaban apagados. De lo contrario, parecía preferir uno de los que se comunican localmente con las bombillas inteligentes.
El protocolo que la aplicación eligió utilizar fue, con diferencia, el resultado más fácil de manejar: 1) era TCP en lugar de UDP, 2) no estaba completamente cifrado. La falta de cifrado es bastante alarmante en retrospectiva, ya que el primer mensaje incluye un token de autorización que nunca parece cambiar para mi cuenta.
Descubrí que los mensajes de la aplicación al servidor se podían "reproducir" de manera efectiva. Una vez que descubrí qué bytes (o "paquetes", gracias al proxy de paquetes) eran para encender y apagar las luces, simplemente podía abrir un nuevo enchufe y enviar estos mismos paquetes y obtener los mismos resultados. Esta fue una gran señal. En el peor de los casos, ya tenía una forma de implementar lo que quería para mí, aunque no fuera muy general.
En este punto, llegó el momento de profundizar en el protocolo. Después de una combinación de experimentación con proxy de paquetes y de profundizar en el desmontaje de Smali, tuve una comprensión bastante general de qué comunicación estaba teniendo lugar. Lo primero que noté fue que la comunicación se realizaba en "mensajes", que comenzaban con un campo de tipo y longitud (en big endian). Lo siguiente fue descubrir qué tipos de paquetes eran cuáles y, finalmente, cómo se codificaban los paquetes específicos. Aquí hay un ejemplo de un paquete del servidor que contiene los estados de mis tres dispositivos:
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
Una vez que tuve suficiente protocolo, creé una API para él. Esta API puede enumerar dispositivos, obtener sus estados y actualizar varias propiedades de los dispositivos (por ejemplo, brillo y tono de color). Sorprendentemente, descubrí que mi API es mucho más rápida y confiable que la aplicación misma. Parece que intentar usar Bluetooth o WiFi antes de recurrir a un servidor remoto hace que la aplicación sea mucho más inestable y menos confiable de lo que podría ser.
Como nota final, no soy propietario de todos los dispositivos compatibles con esta aplicación, por lo que no estaba motivado (ni podía fácilmente) realizar ingeniería inversa sobre cómo funcionarían estos dispositivos. Por ejemplo, la misma empresa produce enchufes, sensores e interruptores de luz inteligentes.