智能設備的聯(lián)動通常采用IFTTT的方式批钠,但這種方式受限于官方軟件提供的功能宇植。想要自主地靈活控制,需要有官方SDK埋心,或知道協(xié)議細節(jié)指郁。本文通過捕獲、分析Broadlink SP設備(含SP2和SP mini)的協(xié)議數(shù)據(jù)拷呆,達到重放(replay)控制的效果闲坎。在這個過程中,對其安全性也有了更深入的認識茬斧。
有前人做過類似的工作腰懂,但抓包過程較為繁瑣。本文的方法比較便捷啥供,可以很容易地進行本地和遠程的分析悯恍。這個方法也可供研究其它智能設備時借鑒。
在路由器上用tcpdump抓包伙狐,基本行為研究
家里的路由器是刷了OpenWRT的涮毫,所以可以直接嘗試在路由器上用tcpdump抓包瞬欧。
實驗1:不打開任何App時,觀察插座上的活動罢防。
命令:tcpdump -i ra0 udp and host sp3 -U -s0 -w /tmp/tmp.pcap -c 30 -vvv
(sp3是我的第3個SP類型的設備艘虎,并不是指型號;上面的命令是抓到30個UDP包就停止)
在Wireshark中打開抓獲的pcap文件:
可以看到:大約每25秒咒吐,插座會向Broadlink的服務器(112.124.35.104)報告一次自己的狀態(tài)野建。可稱之為在線狀態(tài)報告恬叹。
實驗2:在4G網(wǎng)絡下(不用Wi-Fi)候生,打開手機App對應的插座狀態(tài)界面
可以看到刊棕,大約每3秒巧娱,插座會向Broadlink的服務器(112.124.35.104)報告一次自己的開關狀態(tài)靴跛。當然巷挥,數(shù)據(jù)里還有在線狀態(tài)報告垢村。通過包的長度很容易區(qū)分出來掂墓。
3秒的間隔應該是App端決定的弱左,其實是App向Broadlink服務器詢問插座開關狀態(tài)艺普,服務器再來問插座的菱农。
局域網(wǎng)內(nèi)抓包的問題
當手機在家里或在家外時缭付,控制智能插座的原理是不一樣的。手機和插座在同一個局域網(wǎng)內(nèi)時循未,它們是直接通訊陷猫,不需要借助于服務器的。
但在無線路由器上只厘,其實是抓不到兩個Wi-Fi設備之間的通訊的烙丛。也許這些通訊由Wi-Fi硬件直接處理,不經(jīng)過路由器的系統(tǒng)(驅(qū)動)羔味。而且我試了河咽,一方接在2.4G上,另一方接在5G上赋元,也是一樣抓不到數(shù)據(jù)忘蟹。
要抓取局域網(wǎng)內(nèi)的兩個無線設備的通訊,傳統(tǒng)的辦法是把PC變成AP搁凸,讓它們的流量經(jīng)過PC媚值,然后用抓包軟件抓取。但這需要對設備重新部署护糖、配置褥芒,比較折騰。
用無線網(wǎng)卡的monitor模式,使用Wi-Fi sniffer锰扶,也是一種選擇献酗。但對于加密的無線網(wǎng)絡,比較麻煩坷牛。而且是從數(shù)據(jù)鏈路層分析應用層的數(shù)據(jù)罕偎,略感舍近求遠。
因為無線路由器上可以抓到局域網(wǎng)內(nèi)有線設備和無線設備之間的通訊京闰,所以還有另一個選擇:把手機變成有線的颜及!
Android模擬器Genymotion
在PC上運行Android模擬器,我們就有了一個連在有線網(wǎng)絡上的手機了(前提當然是PC連在有線網(wǎng)絡上)蹂楣,從而可以繼續(xù)在無線路由器上抓包俏站。
Android的模擬器有不少,我一般用Genymotion捐迫。Genymotion默認不支持ARM乾翔,但有好人弄了翻譯器。新版的Genymotion好像只在Android 6.0, 5.0上有翻譯器的支持施戴。
當然,如果App支持x86架構(gòu)萌丈,或與架構(gòu)無關(純Java的)赞哗,也是不需要ARM翻譯器的。但Broadlink App(易控)不是這樣的辆雾。
最后肪笋,Broadlink App能在Android 6.0的模擬器上正常運行。
另外度迂,在Genymotion的設置中使用網(wǎng)橋模式藤乙,這樣,模擬器和Broadlink設備在同一網(wǎng)段惭墓。
局域網(wǎng)內(nèi)行為研究
實驗3:在局域網(wǎng)內(nèi)坛梁,Android模擬器上點擊開/關時,在OpenWRT上用tcpdump抓包
這些包里有3秒一次的開關狀態(tài)包腊凶。都是QUIC協(xié)議114字節(jié)划咐。根據(jù)時間的周期性,可以看出哪些包是對應于開關控制的钧萍,比如上圖中的第2和第4個包褐缠。
為了重新發(fā)送這些數(shù)據(jù)包,寫了一個簡單的Python腳本sendpcap.py风瘦,對pcap文件進行簡單解析队魏,主要是確定每個包的分隔,哪些是頭部万搔,哪些是Payload胡桨,并可以發(fā)送指定序號的一個或多個包官帘。
實驗4:在局域網(wǎng)內(nèi),重新發(fā)送pcap里的某個指定的UDP包登失,可以控制SP插座的開和關遏佣。
命令:sendpcap.py sp3 sp3-lan-phone-onoff.pcap 2
發(fā)送第2個包會開啟插座。
盡管每個包的數(shù)據(jù)不完全一樣揽浙,但這些包都可以用于控制插座状婶。實測一年以后還有效(當然,只對于同樣網(wǎng)絡環(huán)境下的同一個設備)馅巷。
所以膛虫,對每個設備采集一段樣本數(shù)據(jù),確定哪個包是控制開的钓猬,哪個包是控制關的稍刀,就可以實現(xiàn)對不同插座的自主控制了。
遠程行為研究
那么敞曹,這種重放機制對于遠程控制插座是否有效呢账月?
對于遠程交互,由于家里路由器上收到的只是進入設備的數(shù)據(jù)澳迫,而且局齿,有些交互數(shù)據(jù)不一定會流入設備(也許是和Broadlink服務器交互)。所以橄登,需要把抓包環(huán)境搭建在遠程端抓歼,抓獲遠程手機端的流出數(shù)據(jù)。
其實拢锹,在root的Android上也可以安裝tcpdump的谣妻。更好的是,Genymotion的Android已經(jīng)自帶tcpdump了卒稳。
實驗5:在遠程網(wǎng)絡上蹋半,在Android模擬器上通過tcpdump抓包
命令:tcpdump -i eth1 -U -c 300 -vvv -w xxx.pcap
結(jié)果出乎意料,沒有任何直接指向家里的數(shù)據(jù)流展哭,只有和Broadlink服務器的數(shù)據(jù)往來湃窍。
用同樣的方法,我們可以重發(fā)這些數(shù)據(jù)包匪傍。下圖中您市,數(shù)據(jù)包128對應于關播座,154對應于開插座役衡。
實驗6:在遠程網(wǎng)絡上茵休,通過重新發(fā)送pcap里的某個指定的包,可以控制家中的SP插座的開和關
命令:sendpcap.py 112.124.42.42 xxx.pcap 154
就這么輕松,發(fā)一個獨立的數(shù)據(jù)包給Broadlink的服務器就能控制家里的插座了榕莺,沒有任何上下文俐芯,數(shù)據(jù)也不會過期(實測一天之后也可以用)。
結(jié)語
有了基于OpenWRT的無線路由器钉鸯,或基于Genymotion的Android模擬器吧史,我們便可以很容易地在路由器或Android上用tcpdump抓取Broadlink SP設備的網(wǎng)絡數(shù)據(jù)包,從而分析其協(xié)議唠雕。
在局域網(wǎng)內(nèi)控制Broadlink插座贸营,并不需要Broadlink服務器的參與;而遠程控制插座岩睁,則都要借助于服務器钞脂。
重新發(fā)送截獲的 UDP/QUIC數(shù)據(jù)包就可以控制插座。不管是SP2捕儒,還是SP mini冰啃,不管是局域網(wǎng),還是遠程的刘莹,都可以阎毅。但必須用在對應環(huán)境下、對應設備的數(shù)據(jù)包点弯。對同一設備净薛,每次抓獲的數(shù)據(jù)包都不完全相同,但用任何一個都有效蒲拉,且不會過期,沒有會話上下文痴腌。
可見雌团,這個安全性是很低的,形象地說士聪,就是“裸奔”锦援。只要在網(wǎng)絡上截獲發(fā)往Broadlink服務器或SP設備的UDP包,便很容易實現(xiàn)“重放攻擊”剥悟。當然灵寺,我們也可以用這一原理來自主地控制插座。比如区岗,我曾用程控電源給鋰電池充電略板,當樹莓派檢測到電流或電壓達到一定值時,便從樹莓派上發(fā)UDP包關閉插座慈缔,從而徹底關閉程控電源叮称; 當電壓過低時,便發(fā)包打開電源充電。這些瓤檐,是用手機App無法整合的赂韵。
所以,這事有兩面性:不安全挠蛉,但便利祭示。
參考
- broadlink的智能插座sp2簡單分析. 沒有去驗證這篇文章中的抓包方式,只是從這篇文章得知重放攻擊的可行性谴古。另一方面說明3年來质涛,Broadlink的這一不安全的方式并沒有改進。
- 博聯(lián)易控App下載. 當前最新的版本確定可以在Genymition的Android模擬器上運行讥电,但需要ARM翻譯器蹂窖。