原标题:小米智能家居设备流量分析及脚本控制
*本文作者:scu-igroup,本文属 FreeBuf 原创奖励计划,未经许可禁止转载。
前言
万物互联的时代即将来临,而现阶段,我们能感触到的,当属智能家居设备了。目前,IoT智能家居设备可谓种类繁多,琳琅满目,我们房间也按照实际需要买了些小米智能家居设备,使用相当方便,下载米家APP,手机上就能操控。那它到底是怎么实现的操控呢,既然,我们是搞流量分析的,那就先从流量开始吧。
当我们开始吧
这次实验主要分析了三款小米的智能家居设备,如下为:
小米空气净化器
小米LED智能台(也可以下载yeelightAPP进行操作)
小米多功能网关
我们就先从空气净化器开始吧,首先需要知道IoT设备的IP地址,这里有两种比较直接的方法知道设备IP地址,第一种是在APP中添加好设备后,查看设备信息;如查看不到,采用第二种方法,即用小米提供的工具miio查看(这部分后门在介绍)。
找到设备的IP之后,就得想办法获取到进出设备的流量数据包,由于是在同一个局域网中,我们采用ARP欺骗攻击,扮演中间人角色,让设备流量从我的主机经过。攻击的工具为著名的ettercap,攻击命令为:
ettercap -ienp3s0 -T -q -M ARP:remote /192.168.9.253// /192.168.9.150//
运行这条命令,会让网关认为我的主机是IoT设备,让设备认为我的主机是网关,以达到窃听流量的目的。该工具在Ubuntu16.04上可直接安装,更多高级用法,读者可自行搜索。
我们首先来看看抓到的数据包,以IP地址为条件过滤一下,如下图所示:
从图中可以看出,设备的命令控制包为UDP传输,既然是UDP协议传输,那么是否可以通过命令包重放攻击来对设备进行控制?
带着这样的疑问,我们先来写一个数据包重放的脚本试一试:
脚本如上所示,红框黄字部分为开\关空气净化器命令字符串的16进制转码,重放开\关空气净化器设备的脚本,运行该程序,发现净化器没有相应。开wireshark抓包,确认数据包已经发送出去,但命令没有生效,怀疑是设备自身有验证。要解决这个问题,只有分析下应用层协议了。分析应用层协议,最好是能拿到网络通信代码,否则将会是一个费时费力的工作。
幸运的是,了解到在homeassistant中可实现对小米设备的集成,并在其中对设备进行管理和操作。Homeassistant,主要以Python语言开发,既然它能操控小米设备,那它底层肯定有相关的函数调用库。带着这个线索,我开始研究homeassistant,在安装的过程中,发现了miio库,由它可实现对小米部分设备的操作,主要参考这篇文章。Github上分享有miio的开源项目,大喜,不由自主先点了个赞。
首先看看这个库中支持的设备有哪些呢,如下图所示:
可以看到,支持的智能家居种类还是不少,但要使用它,还是需要安装一些依赖包,这些依赖包可以用pip3直接安装:
sudo pip3 install -r requirements.txt
再来看看它的源码程序,在miio文件夹下,发现了airpurifier.py和protocol.py,这两个文件,不是我正想要的么,分析之,并了解它们之间的调用关系。
在AirPurifier中,继承了Device类,主要的应用层数据封装和发送都是在Device类中完成。
上图为Device类的初始化函数,由图中看,只需要知道设备的IP地址和token传入即可。先通过miio工具获取ip和token。
在Ubuntu下,先安装miio,再进行设备发现:
npminstall -g miio
miiodiscover
如上图所示,为扫描到空气净化器相关参数,而用到的传输协议可以在protocol.py的message封装中窥探一二。
如上图所示,为应用层各字段封装,data字段为加密字段,这说明想要通过中间人攻击的方式修改该字段的内容,看来不容易。
那么如何用miio的Python库程序,用脚本完成对空气净化器的控制。如下脚本所示:
运行脚本,不一会儿,听到了空气净化器清脆的响声,并且是开一次,关一次,这样循环,刚好同我的程序逻辑一样。直接用miio库开关空气净化器的程序,那再来分析下小米台灯呢。
先来看看miio库是否支持小米智能台灯yeelight,如下所示:
看来是支持的,但仅仅提供很有限的支持,完整的支持要用python-yeelight库。这个库可直接安装,操作也十分方便,如下为开启等操作:
>>> from yeelight import Bulb
>>> bulb = Bulb("192.168.0.5")
>>> bulb.turn_on()
但要使用这个库,需要用YeeLightAPP将台灯设置为开发者/局域网模式。代码如下所示:
初始运行这个脚本,发现存在socket连接不上的错误,原因是小米智能台灯采用的是TCP连接,如果已经有设备连接到台灯,我们再去连接,就会存在连接不上的错误。
解决方法是:
我这里采用了try, except的错误处理方式,遇到错误,继续循环连接。这样可以将原来的连接挤下去,从而只响应脚本的控制命令。果然,这个脚本运行一段时间后(大概40秒左右),台灯开始有规律开关,符合我的脚本逻辑。
对于小米多功能网关,同样具有开发库(见这里,小米真是一家“开放”的企业^^),它的通信协议也是采用的UDP协议,除了key部分用到了加密算法,其他部分为明文传输。也正因为key字段这部分,我们重放数据包却没有成功,返回的数据包中有Invalid key字段。如下图所示:
在整个与网关的通信中,key会不断地进行交换,这可能就是导致我们重放攻击失败的原因。对于脚本控制小米网关设备,它的调用过程稍显复杂,主要是没有弄清它的传参的过程。感兴趣的朋友可以自己去安装一个homeassistant,看在这里面是如何调用相关函数的。到此为止,三款小米设备基本都介绍完了。本文证明了用脚本控制小米的智能家居设备是可行的,虽然只做了简单的开\关测试,但可以做一个抛砖引玉的作用,更多高级脚本的功能探索,感兴趣的朋友可以继续深入下去。
本次实验所有的代码和数据包,见项目:https://github.com/scu-igroup/ControlXiaomiDevices。
总结
小米智能家居设备配合着APP确实方便好用,本想着研究下它的通信协议,没想到在此过程中,发现小米的这些设备都能利用公开的函数库,并编写脚本程序进行控制,实在是意外的收获。大家如果感兴趣,也可以来实验一把,如果有新的点子,欢迎一起交流。
*本文作者:scu-igroup,本文属 FreeBuf 原创奖励计划,未经许可禁止转载。返回搜狐,查看更多
责任编辑: