作為一個IoT發燒友和夜貓子安全研究員,IoT一直吸引著我,因為我們每天使用的IoT應用程序都在讓生活變得更加輕松便利。從使用一個應用程序到監視,控制設備,這是我一直以來想深入的部分,而這一切都在成為可能。
我最近在亞馬遜上為我的書桌買了一個智能LED燈泡,這是一個7瓦的Syska Smartlight Rainbow LED燈,還可以通過應用程序,在安卓移動設備上用藍牙來控制,玩這個燈的時候發現它很有趣,如果whatsapp有新的通知,這個燈就會閃爍。它還能在早上叫醒我,總之我可以用很多方式和它進行交互,但是只能從它自帶的應用程序上操作。
不像市場上其他著名的智能燈泡(比如Philips Hue,LIFX),這款燈泡由印度的一家公司生產,它使用低功耗藍牙(BLE)而不是Wifi,而且沒有API來與定制應用程序交互,我當時還是決定買了它,因為價格便宜(約135人民幣)。
在用了幾個星期后,我決定看看這個外殼底下是什么樣的,我研究藍牙和低功耗藍牙協議已經有一段時間了,所以對這方面有所了解(這得感謝Cypress Semiconductor去年送了我一個PSoC4 BLE 開發板)。BLE(低功耗藍牙,Bluetooth Low energy的縮寫)基本上在通信層上提供了進行用戶定義服務的方法,為生產商在他們正在制造的設備上定義特有的協議配置文件,盡管BLE協議已經有一些已經定義好的配置文件,比如舊版的UART,BLE心率監測器等等,生產商還是可以自由使用所謂的GATT,Generic Attribute Profile,然后創建他們自己的自定義配置文件,這些配置文件決定了它們要如何在主設備和從設備之間發生通信。
事實上,這個燈泡沒有使用基于TCP/IP協議的通信,這就使得逆向變得有點困難了,我的意思是:如果這個燈是在家庭網絡中,事情不就變得更加容易了嗎?我可以用WireShark通過它的MAC或IP來嗅探數據包,然后保存在PCAP文件中方便之后的分析,數據包是很容易嗅探的,基本上類似于中間人這種東西,甚至一個簡單的CLI tcpdump也有用,但是現實是這是使用對等網絡的藍牙,在同一時間內,一個BLE設備只能與一個中心設備通信。
從之前的BLE項目中我了解到Nordic Semiconductor的一款在安卓或IOS上運行的一個神奇的應用程序,它叫nrf connect,可以用來探索設備暴露出的GATT service和characteristic,我可以用它來連接我的燈泡,然后就能知道它的唯一地址(某種MAC地址)還能找到GATT service和響應的characteristic,這是個很好的起點不是嗎?我迅速在我的安卓手機上安裝并打開了nrf connect,打開藍牙并掃描設備,結果迅速出現在屏幕上,名叫“Cnlign”。
連接之后顯示三個GATT service,如下圖所示:
燈泡暴露的三個GATT service中 ,有兩個在大多數BLE設備上通用,它們分別是UUID為01800的Generic access和UUID為01801的Generic Attribute,你可以查看Bluetooth GATT website來查找更多,這些service定義了設備名,設備種類和狀態,如下圖所示:
除了那兩個,還有一個是用戶定義的service,看到128位的UUID,我可以說這是生產商定義的BLE GATT profile。
現在看service,我當時很確定其中一個characteristic就是控制燈泡顏色的,但是之后我非常失望,因為我當時期待能有個叫RGB color或者其他什么的,但是所有service都被標記為unknown characteristic,如果我找到了service的名字,UUID,我就能發送一些數據包看看是什么反應,但事實并非如此,因此下一步只能嗅探BLE應用程序發給燈泡的數據包,我在這次的搜索中知道了設備地址,GATT service和讀取的或寫入的characteristic,這對之后的步驟是很有幫助的。
我聽說過Great Scott的一個叫Ubertooth One的設備,它能嗅探藍牙數據包,但是看到價格和產地,我決定尋找替代方案,經過查找,我發現還有其他Nordic和Cypress Semiconductor的一些硬件,不過研究一個燈泡,卻花費多于一個燈泡的錢,這沒有意義不是嗎?
進一步的谷歌搜索之后,我在StackOverFlow上找到了替代方法,Android 4.4(katkat)可以將藍牙數據包記錄在一個文件中,我深入了解了一下,發現需要啟用開發者模式,連接藍牙設備然后交互,所有記錄將會被記錄到SD卡中的“btsnoop_hci”文件中。
如果你使用的是安卓4.4(kitkat)或更高版本的手機,那么就可以通過設置 –開發人員選項 –啟用藍牙HCI監聽日志來啟用此功能,這是藍牙調試工具的基礎,啟用之后,所有藍牙日志會被記錄到文件“btsnoop_hci”中,我啟用了這個功能,并且運行了控制燈泡的應用程序,和往常一樣改變燈泡的顏色,這次我更多地注意在基本顏色上,比如紅色,藍色和綠色,這將幫助我在分析包時過濾數據流。關掉程序,文件果然生成了!一個不到20Kb的日志文件就能控制燈泡,而不需要拆開它:P
下一步就是將文件拷貝到電腦上,用Wireshark將其可視化,說真的,Wireshark真是個超級棒的工具,通過了解基本的教程,然后動手實踐,就能找到很多有趣的東西。
燈泡工作的方式可能是通過從應用程序中獲取紅,綠,藍或所謂的RGB值,然后通過更改燈炮中相應的LED顏色來響應,也有可能直接使用顏色名稱,然后通過EEPROM中的查找表來映射強度,從幾個過去的RGB LED項目中,我知道任何顏色可以都映射為紅色綠色和藍色強度的值,通常是8位(0-255),0表示關閉,255表示來自RGB的特定顏色的全部強度,這些強度使用來自定時器IC或微控制器的脈寬調制信號(PWM)來改變。我過去已經做過這樣的項目,如果有興趣去查看我的項目IoT Holicay Lights和OpenHAB RGB控制器,這些使用的都是相同的概念。
如果仔細看下面的截圖,你會發現一些有趣的事情,destination有兩個標簽/值:localhost,也就是我們的安卓手機,另一種是“Texas Instruments”,具有特定的唯一地址,谷歌了一下,我發現它是Texas Instruments的基于BLE的芯片“CC2540“,而燈泡用的可能就是這個,我們之前從GATT service收集的UUID也表明是相同的芯片:D 所以現在就算不打開燈泡,我們也知道里面是什么了;)
進一步研究之后,我發現整體通信中涉及的協議種類較少,在Wireshark中可以看到:HCI_E, HCI_C, ATT等等,ATT看起來很有趣,應用ATT過濾器可以只顯示ATT數據包,然后我應用了藍牙邏輯鏈路控制和適配協議(btl2cap)的過濾器,并嘗試分析從本地主機發送到燈泡的數據包。
研究了20-40個數據包之后,我發現了輕微變化的字符串,看下面:
Value: 00100006000a03000101000025ff00000000
Value: 00110006000a030001010049ff0000000000
Value: 00120006000a0300010100ff000000000000
Value: 00130006000a030001010049ff0000000000
Value: 00140006000a03000101000025ff00000000
發現了嗎?再弄個再簡單一點的:
Value: 0010000 6000a0300010100 0025ff 00000000
Value: 0011000 6000a0300010100 49ff00 00000000
Value: 0012000 6000a0300010100 ff0000 00000000
Value: 0013000 6000a0300010100 49ff00 00000000
Value: 0014000 6000a0300010100 0025ff 00000000
第一組顯然是遞增的字符串,可能是某種數據包的序列號(可以是寫指令操作碼或只是數據包號),后一組只是8個零的字符串。 中間的字符串才是重點,和我猜的差不多,6字節的字符串,紅色藍色和綠色各兩個字節。
0025ff –> 00 25 ff (紅色關閉 藍色25 綠色滿密度)
9ff00
ff0000
49ff00
0025ff 等等 ………
通過這種方式,如果你想要產生藍色,可以在8個0和UUID之間加上00ff00,如“00140006000a030001010000ff0000000000”,把這個通過BLE發給燈泡,地址已經從暴露的GATT中知道。理論上很簡單,實際操作中,可能是反轉的字符串,比如不是RGB而是BGR(另一種常見的顏色表示方式),其中0表示全亮度,255表示關閉。
現在我將使用Kali linux,如果你的電腦中有一個集成的藍牙,或者你可以使用支持BLE(LE v4)的USB藍牙適配器,則可以控制燈泡。我很確定我的Macbook Air有一個。 我設置了虛擬機,通過虛擬機的USB傳輸使用主機(Macbook Air)的內置藍牙硬件, 在這一點上,我不知道Kali是否支持驅動。賭一把,我雖然有一個支持藍牙的樹莓派,但是還是想先試一下前者。
在linux虛擬機上,我打開終端檢查設備是否運行:
root@kali:~# hciconfig
hci0: Type: Primary Bus: USB
BD Address: E0:AC:CB:81:CE:37 ACL MTU: 1021:8 SCO MTU: 64:1
UP RUNNING
RX bytes:1859 acl:2 sco:0 events:106 errors:0
TX bytes:3059 acl:3 sco:0 commands:94 errors:0
開心!設備被檢測到了!現在就要安裝所需要的包了。
root@kali:~# apt-get install bluez bluez-hcidump, bluez-tools
運行下面的命令掃描BLE設備:
root@kali:~# hcitool lescan
LE Scan ...
88:C2:55:CA:F0:36 (unknown)
88:C2:55:CA:F0:36 Cnligh
注意:設備Cnligh是我們的燈泡,另一個設備可能是我的智能健身追蹤器。
如果沒找到,請檢查燈泡是否打開,且不要將燈泡連接你的手機,因為它是P2P通信。
接下來我們連接設備:
root@kali:~# gatttool -I
[ ][LE]> connect 88:C2:55:CA:F0:36
Attempting to connect to 88:C2:55:CA:F0:36
Connection successful
[88:C2:55:CA:F0:36][LE]>
在這里,我使用gatttool Bluez程序通過地址連接到燈泡。
注意:如果出現任何錯誤,在/etc/bluetooth/main.conf中添加以下內容:
EnableLE = true // Enable Low Energy support. Default is false.
AttributeServer = true // Enable the GATT attribute server. Default is false.
然后重啟:
root@kali:~# etc/init.d/bluetooth restart
再次嘗試,應該就能成功了。
一旦你連上了燈泡,你就能發現更多:
[88:C2:55:CA:F0:36][LE]> help
help Show this help
exit Exit interactive mode
quit Exit interactive mode
connect [address [address type]] Connect to a remote device
disconnect Disconnect from a remote device
primary [UUID] Primary Service Discovery
included [start hnd [end hnd]] Find Included Services
characteristics [start hnd [end hnd [UUID]]] Characteristics Discovery
char-desc [start hnd] [end hnd] Characteristics Descriptor Discovery
char-read-hnd
char-read-uuid
char-write-req
char-write-cmd
sec-level [low | medium | high] Set security level. Default: low
mtu
[88:C2:55:CA:F0:36][LE]> primary
attr handle: 0x0001, end grp handle: 0x000b uuid: 00001800-0000-1000-8000-00805f9b34fb
attr handle: 0x000c, end grp handle: 0x000f uuid: 00001801-0000-1000-8000-00805f9b34fb
attr handle: 0x0010, end grp handle: 0xffff uuid: 0000f371-0000-1000-8000-00805f9b34fb
[88:C2:55:CA:F0:36][LE]> characteristics
handle: 0x0002, char properties: 0x02, char value handle: 0x0003, uuid: 00002a00-0000-1000-8000-00805f9b34fb
handle: 0x0004, char properties: 0x02, char value handle: 0x0005, uuid: 00002a01-0000-1000-8000-00805f9b34fb
handle: 0x0006, char properties: 0x0a, char value handle: 0x0007, uuid: 00002a02-0000-1000-8000-00805f9b34fb
handle: 0x0008, char properties: 0x08, char value handle: 0x0009, uuid: 00002a03-0000-1000-8000-00805f9b34fb
handle: 0x000a, char properties: 0x02, char value handle: 0x000b, uuid: 00002a04-0000-1000-8000-00805f9b34fb
handle: 0x000d, char properties: 0x20, char value handle: 0x000e, uuid: 00002a05-0000-1000-8000-00805f9b34fb
handle: 0x0011, char properties: 0x0a, char value handle: 0x0012, uuid: 0000fff1-0000-1000-8000-00805f9b34fb
handle: 0x0014, char properties: 0x0a, char value handle: 0x0015, uuid: 0000fff2-0000-1000-8000-00805f9b34fb
handle: 0x0017, char properties: 0x0a, char value handle: 0x0018, uuid: 0000fff3-0000-1000-8000-00805f9b34fb
handle: 0x001a, char properties: 0x0a, char value handle: 0x001b, uuid: 0000fff4-0000-1000-8000-00805f9b34fb
handle: 0x001d, char properties: 0x0a, char value handle: 0x001e, uuid: 0000fff5-0000-1000-8000-00805f9b34fb
handle: 0x0020, char properties: 0x0a, char value handle: 0x0021, uuid: 0000fff6-0000-1000-8000-00805f9b34fb
handle: 0x0023, char properties: 0x0a, char value handle: 0x0024, uuid: 0000fff7-0000-1000-8000-00805f9b34fb
handle: 0x0026, char properties: 0x0a, char value handle: 0x0027, uuid: 0000fff8-0000-1000-8000-00805f9b34fb
handle: 0x0029, char properties: 0x10, char value handle: 0x002a, uuid: 0000fff9-0000-1000-8000-00805f9b34fb
[88:C2:55:CA:F0:36][LE]>
現在我們嘗試通過發送下方字符串來改變燈泡顏色:
[88:C2:55:CA:F0:36][LE]> char-write-cmd 0x0012 00140006000a0300010100ff000000000000
然后果然變成紅色了!!!視頻在下面。
再試試藍色:
[88:C2:55:CA:F0:36][LE]> char-write-cmd 0x0012 00140006000a030001010000ff0000000000`
再試試綠色:
[88:C2:55:CA:F0:36][LE]> char-write-cmd 0x0012 00140006000a03000101000000ff00000000`
一切都在按預期發生。
演示
為了演示工作,我準備了一個小的bash腳本,將燈泡的顏色循環到紅色 –>綠色 –>藍色 –>白色 –>關閉
#!/bin/bash
echo"Controlling SYSKA Smart light bulb"
sleep 3
echo"Look Mah! No App "
sleep 3
while true;
do
gatttool -i hci0 -b 88:C2:55:CA:F0:36 --char-write-req -a 0x0012 -n 00100006000a030001010000000000000000 >/dev/null
sleep 3
echo"RED"
gatttool -i hci0 -b 88:C2:55:CA:F0:36 --char-write-req -a 0x0012 -n 00100006000a0300010100ff000000000000 >/dev/null
sleep 3
echo"GREEN"
gatttool -i hci0 -b 88:C2:55:CA:F0:36 --char-write-req -a 0x0012 -n 00100006000a030001010000ff0000000000 >/dev/null
sleep 3
echo"BLUE"
gatttool -i hci0 -b 88:C2:55:CA:F0:36 --char-write-req -a 0x0012 -n 00100006000a03000101000000ff00000000 >/dev/null
sleep 3
echo"WHITE"
gatttool -i hci0 -b 88:C2:55:CA:F0:36 --char-write-req -a 0x0012 -n 00100006000a0300010100ffffff00000000 >/dev/null
sleep 3
echo"OFF"
gatttool -i hci0 -b 88:C2:55:CA:F0:36 --char-write-req -a 0x0012 -n 00100006000a030001010000000000000000 >/dev/null
done
exit 0
GitHub上也有。
您可以使用顏色選擇器(如HTML顏色選擇器)中的RGB值來模擬任何顏色。
視頻
思考
雖然這是一個有趣的逆向IoT設備的功能的項目,但看到數據包不是加密的,我仍然很傷心,很多公司專注于縮短他們的物聯網產品的上市時間,但在這個過程中,他們并沒有采取最大的措施來確保設備的安全,這只是一個藍牙智能電燈泡,不會搞出大新聞,黑客最多也只能改變你家里的燈泡顏色,但是如果智能鎖也是這樣,那么麻煩就大了,你的車庫和家門就會受到很大威脅。或者一個基于tcp的設備,可以在DDoS攻擊時充當僵尸網絡的一員,令人失望的是生產商只是簡單地參照了示例代碼, 甚至不改變藍牙協議本身提供的128位UUID靈活性。
下一步
我現在有了API,正在計劃一個小型項目,從Yahoo Weather或Weather Underground等在線服務中獲取我的位置的天氣數據,并使我的燈泡天氣變化實時反應,例如雨天呼吸藍色,陽光充足就用白色,溫暖的一天用橙色。 我可以使用Python Bluez API(pyBlue或其他)。請保持關注,另外,感謝閱讀:)