Untuk proyek ini, saya merekayasa balik aplikasi "C by GE" untuk mengendalikan bola lampu pintar GE yang terhubung dengan WiFi. Untuk melakukan ini, saya mulai dengan mendekompilasi aplikasi Android, dan kemudian merekayasa balik protokol biner yang digunakan aplikasi untuk berkomunikasi dengan server. Untuk lebih jelasnya, lihat Reverse Engineering C oleh GE.
Produk akhir dari proyek ini adalah:
Penafian: kode ini adalah hasil rekayasa balik dan belum diinformasikan oleh spesifikasi protokol. Oleh karena itu, tidak ada jaminan bahwa ini akan terus berfungsi atau akan berfungsi pada setiap jaringan atau perangkat pintar. Meskipun orang lain telah berhasil menggunakan API ini dalam beberapa kasus, ada kemungkinan bahwa kode tersebut membuat asumsi yang salah yang tidak berlaku dalam setiap kasus penggunaan.
Direktori server adalah aplikasi web mandiri dan titik akhir API JSON untuk bola lampu C by GE. Situs webnya terlihat seperti ini:
Jika Anda menjalankan situs web dengan argumen -email
dan -password
, maka situs web akan menampilkan halaman autentikasi dua faktor saat pertama kali Anda memuatnya. Anda akan menekan tombol dan memasukkan kode verifikasi yang dikirimkan ke email Anda. Alternatifnya, Anda dapat login terlebih dahulu dengan menjalankan perintah login_2fa dengan flag -email
dan -password
yang disetel ke informasi akun Anda. Perintah tersebut akan meminta Anda memasukkan kode verifikasi 2FA. Setelah Anda memasukkan kode ini, perintah akan mengeluarkan info sesi sebagai gumpalan JSON. Anda kemudian dapat meneruskan JSON ini ke argumen -sessinfo
di server, misalnya sebagai -sessinfo 'JSON HERE'
. Perhatikan bahwa bagian dari sesi akan berakhir setelah satu minggu, namun instance server yang sedang berjalan akan terus berfungsi setelah waktu ini karena bagian sesi yang dapat kedaluwarsa hanya digunakan satu kali untuk menghitung perangkat.
Akun yang lebih baru memerlukan penggunaan otentikasi dua faktor. Anda dapat melakukan jabat tangan 2FA untuk membuat sesi seperti ini:
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...
Untuk akun lama yang belum pernah menggunakan 2FA sebelumnya, Anda mungkin bisa langsung login:
session , err := cbyge . NewControllerLogin ( "my_email" , "my_password" )
// Handle error...
Setelah Anda mengadakan sesi, Anda dapat menghitung perangkat seperti ini:
devs , err := session . Devices ()
// Handle error...
for _ , x := range devs {
fmt . Println ( x . Name ())
}
Anda dapat mengontrol bohlam seperti ini:
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)
Anda juga dapat menanyakan setelan bohlam saat ini:
status , err := session . DeviceStatus ( x )
// Handle error...
fmt . Println ( status . IsOn )
fmt . Println ( status . ColorTone )
Di bagian ini, saya akan memandu Anda mempelajari cara saya merekayasa balik bagian-bagian protokol C by GE.
Langkah pertama adalah membongkar aplikasi Android dengan Apktool. Ini menghasilkan pembongkaran Smali untuk aplikasi tersebut. Melihat-lihat, saya mencari URL dan nama domain. Awalnya, saya menemukan ini:
.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/ "
Melihat di mana titik akhir API ini digunakan dengan cepat mengarahkan saya ke serangkaian panggilan HTTP berbasis JSON untuk masuk, membuat daftar perangkat, dll. Namun, titik akhir ini tampaknya tidak memberikan cara untuk 1) mendapatkan status perangkat, atau 2) perbarui warna atau kecerahan perangkat.
Pasti ada cara lain bagi aplikasi untuk berkomunikasi dengan bohlam smart. Namun, pembongkaran tersebut penuh dengan kode untuk komunikasi Bluetooth dan LAN, dan saya agak khawatir tidak ada titik akhir API global untuk mengendalikan bohlam. Yang lebih parah, aplikasi C by GE mengeluh setiap kali saya mematikan Bluetooth dan kemudian mencoba menggunakannya. Namun, saya akhirnya menemukan bahwa saya dapat membuka aplikasinya, membiarkannya melakukan tugasnya, lalu mematikan Bluetooth dan WiFi sambil tetap mengontrol bohlamnya. Yang harus saya lakukan hanyalah menekan tombol "kembali" Android setiap kali aplikasi membuka popup yang meminta saya untuk "Aktifkan Pelacakan Lokasi" (nama aneh untuk Bluetooth dan WiFi, ingatlah).
Pada titik ini, saya cukup yakin aplikasi tersebut tidak membuat koneksi HTTP(S) misterius lainnya. Menariknya, saya menemukan domain "xlink.cn" di tempat lain dalam kode 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
Astaga, mungkinkah ini protokol berbasis soket mentah? Saya mencobanya, dan benar saja saya dapat membuka koneksi TCP ke cm-ge.xlink.cn:23778
. Namun, Smali juga penuh dengan logika untuk paket UDP , jadi saya tidak yakin protokol mana yang akan digunakan oleh aplikasi tersebut. Dengan pemikiran ini, saya membuat proxy paket dan mengaturnya mendengarkan pada port 23778. Kemudian saya mengganti domain cm-ge.xlink.cn
dengan alamat IP saya di kode Smali, mengkompilasi ulang aplikasi menjadi APK, dan menginstalnya di telepon saya.
Benar saja, aplikasi C by GE saya yang telah dipatch segera terhubung ke instance paket proxy saya dan mulai mengobrol. Khususnya, ini hanya terjadi ketika Bluetooth dan WiFi dimatikan. Jika tidak, tampaknya ia lebih memilih salah satu yang berkomunikasi secara lokal dengan bohlam pintar.
Sejauh ini, protokol yang dipilih oleh aplikasi adalah hasil yang paling mudah untuk ditangani: 1) menggunakan TCP, bukan UDP, 2) tidak terenkripsi sama sekali. Kurangnya enkripsi cukup mengkhawatirkan, karena pesan pertama menyertakan token otorisasi yang sepertinya tidak pernah berubah untuk akun saya.
Saya menemukan bahwa pesan dari aplikasi ke server dapat "diputar ulang" secara efektif. Setelah saya mengetahui byte mana (atau "paket", berkat proxy paket) yang digunakan untuk menyalakan dan mematikan lampu, saya cukup membuka soket baru dan mengirim paket yang sama dan mendapatkan hasil yang sama. Ini adalah pertanda bagus. Skenario terburuknya, saya sudah memiliki cara untuk mengimplementasikan apa yang saya inginkan untuk diri saya sendiri, meskipun itu tidak terlalu umum.
Pada titik ini, sudah waktunya untuk menggali lebih dalam mengenai protokol. Setelah kombinasi eksperimen dengan proxy paket dan menggali pembongkaran Smali, saya memiliki pemahaman yang cukup umum tentang komunikasi apa yang sedang terjadi. Hal pertama yang saya perhatikan adalah komunikasi terjadi dalam "pesan", yang dimulai dengan jenis dan panjang bidang (dalam big endian). Hal berikutnya adalah mencari tahu jenis paket mana, yang mana, dan pada akhirnya bagaimana paket spesifik itu sendiri dikodekan. Berikut contoh paket dari server yang berisi status ketiga perangkat saya:
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
Setelah saya merasa cukup dengan protokolnya, saya membuat API untuk itu. API ini dapat membuat daftar perangkat, mendapatkan statusnya, dan memperbarui berbagai properti perangkat (misalnya kecerahan dan nada warna). Anehnya, saya menemukan API saya jauh lebih cepat dan lebih dapat diandalkan dibandingkan aplikasi itu sendiri. Tampaknya mencoba menggunakan Bluetooth atau WiFi sebelum kembali ke server jarak jauh menyebabkan aplikasi menjadi lebih lemah dan kurang dapat diandalkan dibandingkan yang seharusnya.
Sebagai catatan terakhir, saya tidak memiliki semua perangkat yang didukung oleh aplikasi ini, jadi saya tidak termotivasi (atau dapat dengan mudah) untuk merekayasa balik cara kerja perangkat ini. Misalnya, perusahaan yang sama memproduksi stopkontak pintar, sensor, dan sakelar lampu.