我是如何Hack一個機器人的?
在Hack Day這樣的偉大節日里,還是應該做一點Hack的事。很久沒有干過這么刺激的事,想想也覺得有點小激動。
Blabla,當然這個Robot可能沒有你想的那么高端,Hack的目的只是為了控制這個機器人。而這個所謂的機器的主要功能都集中在客戶端上,我們可以在手機上通過BLE(藍牙低功耗)來控制這個機器人。
所以,我們的目的其實很簡單——自己寫APP來控制這個機器人。而APP的主要功能都是通過藍牙控制來實現的,而藍牙協議的第一步就是連接。在最開始的時候我想的連接方式是PIN碼 + AT指令,結果發現我完全錯了,BLE實際上更簡單。
因此,我覺得有PIN碼的存在,所以第一步就是抓包。
藍牙通訊抓包一
為了做到這一步,我們需要一個大名鼎鼎的“WireShark”。不過,我們是要拿這個軟件來分析日志。
第一步,我們需要在開發者選項中啟用日志分析。在開發者選項中有一個功能, [Enable Bluetooth HCI snoop log/啟用藍牙 HCI 信息收集日志]。如下圖所示:
第二步,我們我們就可以打開應用,做一些正常的操作,然后這些操作就會存儲到一個日志文件里。而這個日志文件只能用WireShark打開。
第三步,就是用WireShark打開這個日志。從日志中找尋手機發往機器人的指令,發現里面都看不懂。
接著想起來,似乎可以反編譯他們的代碼。
反編譯代碼
開始嘗試反編譯代碼,發現步驟也挺簡單的:
- 用apktool反編譯apk
- 用dex2jar將dex轉為jar
- 用jd-gui查看反編譯后的軟件,并導出
- 查看代碼
雖說原理很簡單,但是實踐起來就坑了。先反編譯了最新的APK,然后發現這個APK被360加固了。。接著開始回溯這個軟件的版本,360加固出得比這個軟件晚,那么我應該可以找到這個軟件的早期版本。
而事實是,我在國內都找不到這個APK的早期版本,只好拿包名去搜索,然后中獎了——找到了一個早期的版本,并且反編譯成功了。
接著,我全局搜索PIN碼等等的東西都沒有結果,我的思路錯了。。。
最后,我看到了代碼里的:
Log.i("robotControl", "forward left 30");
既然,他可以打日志,那我應該是可以查看日志的。
日志記錄
于是,我找到了Android的logcat命令,然后湊了一條指令出來。
adb -d logcat com.example:D *:D > debug.log
運行軟件,分析日志。從大量的數據里找到:
D/BluetoothAdapterService(23908452)(16911): getState() - mAdapterProperties: com.android.bluetooth.btservice.AdapterProperties@1e554c00
D/BluetoothAdapter(17239): 448307125: getState(). Returning 12
D/BtGatt.GattService(16911): registerClient() - UUID=037decf9-4d7e-49d8-9f82-85202eea480f
看著日志,看著日志。突然有一個瞬間,我意識到BLE是不需要PIN碼的。我只需要找到對應的UUID,以及對應的Service就可以了。
現在,我可以寫自己的應用了。
編寫自己的APP
這一次,在網上簡單地找了一個Cordova BLE的示例。(后面才發現這個坑挖得太深,以至于掉了進去。Cordova對WebSocket的支持不好,不過這和這個主題沒有啥關系。。)
分析設備
按代碼的邏輯,我們可以在連接上設備的時候查看設備的服務——并根據具體的服務及txCharacteristic,來做對應的發送數據。而依據write數據的代碼,我們需要兩個東西一個是設備的UUID,一個Characteristic。一個藍牙4.0的終端可以包含多個Service,一個Service可以包含多個Characteristic。
如,我們要發送和接收數據都需要有對應的Characteristic。藍牙技術聯盟似乎定義了一些GATT(Generic Attribute Profile ),如下是一個設備的縮略數據:
{
"name": "Battery Demo",
"services": [
"1800"
],
"characteristics": [
{
"service": "1800",
"characteristic": "2a00",
"properties": [
"Read"
]
}
]
}
如這個設備,提供了一個代碼為1800的服務。這個服務里包含了一個characteristic為2a00的屬性,我們只需要通過1800這個Service UUID,以及characteristic 2a00就可以讀取這個設備的Device Name——這個是藍牙技術聯盟定義的Characteristics。
而這時,就找到了UUID為fff0,TX Characteristic為fff1。
控制機器人
所以我們的設備信息便如下所示:
var robotInfo = {
serviceUUID: "0000fff0-0000-1000-8000-00805f9b34fb",
txCharacteristic: "0000fff2-0000-1000-8000-00805f9b34fb", // transmit is from the phone's perspective
rxCharacteristic: "0000fff1-0000-1000-8000-00805f9b34fb" // receive is from the phone's perspective
};
接著,繼續看之前的反編譯代碼,發現他是這么控制的。
- 左轉指令X2
- 右轉指令X3
- 前進指令X1
- 后退指令X4
當然,他還有更多的指令,只是我不需要那么多。。。然后我找到了一個名為nipplejs的庫,來當游戲手柄。
小結
現在,我們已經可以控制這個機器人了。
來自: http://www.phodal.com/blog/how-to-hack-a-robot/