freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

手上有啥就搞啥(五) 小米电力猫
2023-03-02 13:37:43
所属地 江苏省

本篇是”手上有啥就搞啥“系列的第五篇,研究对象是小米电力猫,侧重点是固件逆向协议分析

近几年电力猫已逐步被Mesh组网取代,但笔者一直对电力猫的原理比较好奇,正好利用此次设(po)备(lan)研究机会给自己做个科普。

内容主要包括:

  • 0x00 基础知识:电力猫简介与工作原理

  • 0x01 站在巨人肩上:设备信息与资源下载

  • 0x02 自己动手做:固件逆向与协议分析

  • 00x3 做个总结:简单总结

  • 0x04 参考资料:参考链接

往期回顾:

手上有啥就搞啥(一) — 小米手环3

手上有啥就搞啥(二) — 猫盘

手上有啥就搞啥(三) — WiFi信号放大器

手上有啥就搞啥(四) — H3C 智能摄像头

0x00 基础知识

0x00 - 00 电力猫简介

电力猫比较专业的描述是“电力网络路由器”(或“电力线通信”),英文缩写为 PLC(Power Line Communication)。该技术可利用电力线传输数据和媒体信号的。其原理是把载有信息的高频加载于电流然后用电线传输接受信息的适配器再把高频从电流中分离出来并传送到计算机或电话以实现信息传递。

0x00 - 01 电力猫工作原理

抛开细节实现,电力猫的工作原理也很简单,即在发送时,利用调制技术将用户数据进行调制,把载有信息的高频加载于电流,然后在电力线上进行传输;在接收端,先经过滤波器将调制信号取出,再经过解调,就可得到原通信信号,将数据传输到联网设备。

其核心技术是正交频分复用(OFDM),简单点说就是把互联网信号和电力信号叠加到一起。我们平时用的电都是交流电,频率是50HZ,电力猫就是在交流电的基础上叠加上互联网的信号。因为互联网的信号频率都很高(10MHz甚至更高)所以如果采用合适的手段,是不会对电力传输产生影响的。

这种技术在别的场景也很常见,比如用电话线ADSL上网等技术,都是在语音信号上叠加了一个更高频的互联网信号,由于频率太高,人类的耳朵是听不到的,语音通话会忽略这种信号(认为是杂波),只有高频的收发设备才能分离这些信号并加以处理。

0x01 站在巨人肩上

0x01 - 00 设备信息

购买页面能得到设备处理器和系统信息:

两种类型设备都使用高通处理器,其中主猫处理器型号为QCA6410,经查询是为实现 **HomePlug AV (HPAV)**标准器的处理器。

HomePlug AV是家庭电力线网络联盟(HomePlug Powerline Alliance)为满足家庭数字多媒体传输的需要而制定的标准,能实现在电力线、电话线、以及同轴电缆上数据传输。其规范描述了一种以 200 Mbps 运行的 PLC 系统,该系统基于基于正交频分复用(OFDM) FFT 的物理层(PHY)协议和混合 TDMA/CSMA 媒体访问控制(MAC)协议。CSMA 组件与 HomePlug 1.0.1 CSMA 技术中使用的组件相同。OFDM FFT 使用 1.8–30 MHz 的频带,调制高达 1024 QAM 和 turbo 卷积码 FEC。HomePlug AV 是电力猫实现数据电线传输的核心

子猫处理器为QCA9533,经查询得知为MIPS架构,系统基于OpenWRT,也就是有文件系统的Linux

0x01 - 01 硬件拆解

恩山无线也有小伙伴做过硬件拆解。由于笔者之前对 PLC的技术并不了解 ,处理了一些基本信息,在板子上并没有得到更多线索。

和商品信息页相符合,主猫处理器为QCA6410

子猫处理器是QCA9533

0x01 - 02 资源下载

0x02 自己动手做

通过 PLC原理可以得知,主猫的功能是将网络信号转化成电信号传输,子猫端解调还原,并通过(有/无线)网络和设备通信,回流数据过程相反。网络通信部分无太多疑问,关键看固件中 PLC 的实现传输中的数据协议

0x02 - 00 固件逆向

对于 PLC功能来说,主子猫两端功能基本对等,这里选取研究成本较低的子猫(基于OpenWRT)作固件分析。

直接 Binwalk分析提取 rootfs

iot@attifyos ~/Documents> binwalk -Me p01.bin 

Scan Time:     2023-02-22 18:02:30
Target File:   /home/iot/Documents/p01.bin
MD5 Checksum:  f2f7d448d296a821b0d593bb88d543f7
Signatures:    396

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
458752        0x70000         JFFS2 filesystem, big endian
990212        0xF1C04         JFFS2 filesystem, big endian
993772        0xF29EC         JFFS2 filesystem, big endian
994688        0xF2D80         JFFS2 filesystem, big endian
998244        0xF3B64         JFFS2 filesystem, big endian
1000132       0xF42C4         JFFS2 filesystem, big endian
1003880       0xF5168         JFFS2 filesystem, big endian
......
1124812       0x1129CC        JFFS2 filesystem, big endian
1245184       0x130000        uImage header, header size: 64 bytes, header CRC: 0xFD10DD0F, created: 2017-06-06 08:39:12, image size: 1047183 bytes, Data Address: 0x80060000, Entry Point: 0x80060000, data CRC: 0xE474F6E1, OS: Linux, CPU: MIPS, image type: Multi-File Image, compression type: lzma, image name: "MIPS OpenWrt Linux-3.3.8"
2293760       0x230000        Squashfs filesystem, little endian, version 4.0, compression:xz, size: 6307402 bytes, 885 inodes, blocksize: 262144 bytes, created: 2017-06-06 08:39:10
8978432       0x890000        uImage header, header size: 64 bytes, header CRC: 0xFD10DD0F, created: 2017-06-06 08:39:12, image size: 1047183 bytes, Data Address: 0x80060000, Entry Point: 0x80060000, data CRC: 0xE474F6E1, OS: Linux, CPU: MIPS, image type: Multi-File Image, compression type: lzma, image name: "MIPS OpenWrt Linux-3.3.8"
8978504       0x890048        LZMA compressed data, properties: 0x6D, dictionary size: 8388608 bytes, uncompressed size: 3030140 bytes
10027008      0x990000        Squashfs filesystem, little endian, version 4.0, compression:xz, size: 6307402 bytes, 885 inodes, blocksize: 262144 bytes, created: 2017-06-06 08:39:10

Scan Time:     2023-02-22 18:03:10
Target File:   /home/iot/Documents/_p01.bin.extracted/890048
MD5 Checksum:  51e3e4a9a3cf031783037ae33a50af58
Signatures:    396

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------

简单看一下文件和架构:

可以看到,固件结构十分清晰;小米工程师十分调皮。设备为MIPS大端,有兴趣的小伙伴可在 0x01 - 02 资源下载中自行下载研究,以下直接开始分析 PLC 实现部分。

  • 静态分析

首先是定位 PLC 相关程序和配置,开局一个字符串,后面全靠猜。

简单浏览文件系统目录,从经验出发,相关程序应该存在 /usr/sbin中,本着相信程序猿规范的原则,从简单的字符串搜索开始。

/usr/sbin目录下暴力搜索结果:

iot@attifyos ~/D/_/s/u/sbin> grep -r plc
Binary file plchost matches
Binary file plclog matches
Binary file plclist matches
ft_test.sh:	echo "mac plc=`getmac plc`" >> $tfile
ft_test.sh:	echo "plc_dek=`bdata get plc_dak`" >> $tfile
ft_test.sh:	echo "    check avlnmembership: 0, in avln, rsta equal to plc macaddr" >> $tfile
ft_test.sh:	. /lib/plc/libplc.sh
Binary file hpavkey matches
Binary file modpib matches
Binary file plcstat matches
plwbc_sync.sh:	[ -z "$ssid" ] && ssid="xiaomi-plc-v1_miap$suf"
gw_dog.cron:log_plc()
gw_dog.cron:    # check if plc is down, just swap xqled to wan_invalid!
gw_dog.cron:    . /lib/plc/libplc.sh
gw_dog.cron:    LOGI " extract plc log when $mode gateway with $1! "
gw_dog.cron:    local fname=plc-${ts}-$type
gw_dog.cron:    plclog -i $ndev -x >/tmp/$fname.log
gw_dog.cron:    mkdir -p /data/debug_plc
gw_dog.cron:    mv /tmp/$fname.tar.gz /data/debug_plc/
gw_dog.cron:    local size=`du -s /data/debug_plc | awk '{print $1}'`
gw_dog.cron:        tar -zcf /tmp/plc-${ts}-gw.tar.gz debug_plc/
gw_dog.cron:        log_upload -a /tmp/plc-${ts}-gw.tar.gz
gw_dog.cron:        rm -rf /data/debug_plc /tmp/plc-${ts}-gw.tar.gz
gw_dog.cron:    echo "@@@@@@@@@@ plc phy data rate info !!!" >> $tfile
gw_dog.cron:    plcrate -i $dev -n 2>&1 >> $tfile
gw_dog.cron:            [ "plc_nomatch" = "`uci -q get xqled.active.func`" ] || xqled wan_invalid
Binary file plctool matches
autobind.sh:# check network is up? in case of the situation plc reset after triggered plwbc.
Binary file plcID matches
autobind_plwbc.sh:	. /lib/plc/libplc.sh
autobind_plwbc.sh:	# translate plcsta to ethmac
Binary file chkpib matches
log_collection.sh:[ -d /data/debug_plc ] && p01_list="$p01_list /data/debug_plc/"
autobind_trafficd.sh:    [ -z "$ssid" ] && ssid="xiaomi-plc-v1_miap$suf"
Binary file plcfwd matches
Binary file setpib matches
Binary file plcrate matches
Binary file plcdevs matches
Binary file plcrule matches

初步判断,以 plc为前缀的二进制和配置文件都与 PLC过程相关,先锁定了 /etc/init.d/plchost/usr/sbin/plchost,前者为配置文件,后者为二进制文件。

配置文件用于启动/关闭/重启 PLC服务,其调用了 /usr/sbin/plchost

再来看 plchost 程序,没有符号 ~.~:

只能先从字符串出发,看到一些比较具有代表性的,于是上网搜一搜,收获满满:

Qualcomm Atheros Open Powerline Toolkit搜到了相同字符串定义,说明整个 PLC实现可能基于开源代码,研究渐入佳境。

下载编译 open-plc-utils作个对比,该工具编译很是丝滑, make即可。完成编译后可执行文件在 plc文件夹下生成,通过和 rootfs对比,不能说十分相似,只能说一模一样

  • 动态模拟

由于找到源码,动态模拟并非必要,这里只简单提及。调试当然首选实体设备,利用修改固件包升级大法,适用于升级方便的路由器等设备。如果只想简单模拟或刷机条件较高可利用 qemu + chroot,先测试 busybox有哪些命令:

再获取 shell:

命令比较少,busybox官网下载一个替换:

重新获取 shell:

0x02 - 01 协议分析

open-plc-utils有详尽的文档和代码注释,为协议分析提供良好基础,时间原因笔者没能仔细研读,只在需要的时候查询。

open-plc-utils编译生成的文件中看到有 plchostplchostd,猜测是 PLC的客户端和服务端。

主要实现代码在 plchost.c中,其主要作用已在注释明确:

关键的 plc结构体可在 plc.h中找到:

typedef struct plc

{
	struct channel * channel;
	struct message * message;
	void * content;
	ssize_t packetsize;
	uint8_t MAC [ETHER_ADDR_LEN];
	uint8_t RDA [ETHER_ADDR_LEN];
	uint8_t NMK [HPAVKEY_NMK_LEN];
	uint8_t DAK [HPAVKEY_DAK_LEN];
	struct _file_ CFG;
	struct _file_ cfg;
	struct _file_ SFT;
	struct _file_ sft;
	struct _file_ NVM;
	struct _file_ nvm;
	struct _file_ PIB;
	struct _file_ pib;
	struct _file_ XML;
	struct _file_ rpt;
	struct _file_ socket;
	uint32_t hardwareID;
	uint32_t softwareID;
	uint32_t cookie;
	uint8_t action;
	uint8_t sector;
	uint8_t module;
	uint8_t pushbutton;
	uint8_t readaction;
	uint8_t coupling;
	unsigned flash_size;
	unsigned state;
	unsigned timer;
	unsigned sleep;
	unsigned count;
	unsigned index;
	flag_t flags;
	flag_t flag2;
}

PLC;

通过查询得知 plchost的用法,需要 .pib.nvm文件:

.pib.nvm的使用查询 open-plc-utils文档,搜索引擎,或者问 ChatGPT,这里笔者选择了回到设备 PLC启动脚本,上文提及,在 /etc/init.d/plchost中,定义了所需要的 .pib.nvm

local FILE_NVM="/lib/plc/qca6410.nvm"
local FILE_PIB="/etc/user.pib"

两个都是二进制数据,不可执行,看 start函数中查看调用 $FILE_PIB

mfg_cur=`modpib -v $FILE_PIB | awk '/MFG/ {print $3}'`
mac_cur=`modpib -v $FILE_PIB | awk '/MAC/ {print $2}'`
dak_cur=`modpib -v $FILE_PIB | awk '/DAK/ {print $2}'`
nmk_cur=`modpib -v $FILE_PIB | awk '/NMK/ {print $2}'`

显然是从 pib中读取了某些信息,可以直接或者 chroot执行,结果如下:

可以看出 MFG 和 MAC 没什么可解释的,主要是 DAKNMK,目测是密钥,实际上也确实,DAKDirect Access KeyNMKNetwork Membership Key

.pib存储了 MAC/密钥/…/ 等配置,接着在 start 函数中看$FILE_NVM 的调用:

plc_load函数在libplc.sh中:

这里的 NVM当然不是 Node管理器,而是非易失性存储器 (Non-volatile Memory)NVM在芯片电源关闭期间保存存储在其中的数据。

启动过程还是比较清晰的,再来看细节部分,关键函数是 HostActionResponse

用于发送数据包,在添加了两个 header 后按之前设置的 channel 发送:

通过查看 QualcommHeader函数与协议对比一致:

后续分析测试过程常规且枯燥,这里不再赘述,直接看主猫子猫的通信过程:

# 配对
主猫发送广播包 -> 子猫发送确认应答包
# 通信
子猫发送网络数据请求包 -> 主猫相应并回传数据

两个设备之间使用 AES128 CBC模式加密通信,DAK用于注册,NMK用于网络通信,对加密通信细节感兴趣的小伙伴可参考 HomePlug AV Security Mechanisms这篇论文,还有相关的 通过PLC作网络渗透的文章。

0x03 做个总结

本篇针对小米电力猫作了固件和协议方面分析,虽然电力猫有些过时,但在这个低碳的智能电力时代,相关的安全威胁必将不断涌现。由于能力和时间的原因,对 PLC原理性的阐释有些混乱,动态抓包分析这块也较为粗略,下个设(po)备(lan)见吧。

0x04 参考资料

无线电力猫_百度百科

电力猫 - 知乎

1 Homeplug AV 协议介绍_homeplug green phy_qq_32166451的博客-CSDN博客

电力猫工作原理_百度知道

电力猫的工作原理是什么? - 知乎

小米WIFI电力猫拆解-小米无线路由器以及小米无线相关的设备-恩山无线论坛 - Powered by Discuz!

Tagged - power line communication

hack plc(Power Line Communication)

https://github.com/0x90/powerline-arsenal

QCA6410-68pin-QFN 高通电力载波 - 百度文库

【转载】ROM、RAM、FLASH、NVM……详解_nvm和flash_尘缘里的记忆的博客-CSDN博客

Vulnerability: Infiltrating a network via Powerline (HomePlugAV) adapt

# 固件逆向 # PLC # IoT固件
本文为 独立观点,未经允许不得转载,授权请联系FreeBuf客服小蜜蜂,微信:freebee2022
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
  • 0 文章数
  • 0 关注者
文章目录